使用权限从python运行shell脚本

我有最简单的脚本叫做update.sh

 #!/bin/sh cd /home/pi/circulation_of_circuits git pull 

当我用./update.sh从terminal调用这个./update.sh我得到了一个已经是最新的或者更新了文件。

我也有一个python脚本,里面那个scipt是​​:

subprocess.call(['./update.sh'])

当调用相同的脚本时,我得到:

权限被拒绝(publickey)。 致命的:无法从远程存储库读取。

请确保您拥有正确的访问权限并存在存储库。

(我使用SSH)。

—————–更新——————–

有人找我:

OK,所以有一些进展。 当我启动你的镜像时,我不能在你的repo目录下运行git pull,而bash脚本也会失败。 这似乎是因为bitbucket存储库是私人的,需要validation拉(我使用的是公开的,所以这就是为什么我没有问题)。 大概git会在第一次input之后记住这个,bash不知何故会欺骗git,认为这是你随后input的命令,但是从python运行它并不一样。

我不是一个混帐专家,但必须有一些方法来设置这个python可以提供身份validation。

听起来像你需要给你的SSH命令一个公共或私人的密钥,它可以访问:

 ssh -i /backup/home/user/.ssh/id_dsa user@unixserver1.nixcraft.com 

– 我告诉它在哪里寻找钥匙

这个问题是由git repo身份验证失败造成的。 你说你正在使用SSH,而git抱怨公钥认证失败。 通常你可以在私人仓库上使用git命令而不用输入密码。 所有这一切意味着git使用ssh,但在后一种情况下,它找不到正确的私钥。

由于这个问题只有在运行另一个脚本时才会显现出来,这很可能是由于环境变量的混乱造成的。 Subprocess.call应该按原样传递环境,所以有一些常见的嫌疑犯:

  1. 须藤。
    • 如果您使用的是sudo,则会将大部分空的环境传递给进程
  2. python脚本本身
    • 如果python脚本改变它的env,那么这些改变也会传播到子进程中。
  3. sh -lsu -
    • 这些命令设置了一个登录shell,这意味着它们的环境被重置为默认值。

任何这些原因都可能隐藏环境变量ssh-agent(或其他一些密钥管理工具)可能需要工作。

诊断和修复的步骤:

  1. 隔离问题。

    • 创建一个最小化的python脚本,除了运行subprocess.call(['./update.sh']) 。 运行update.sh和新脚本。
  2. 诊断问题并相应地修复:

    a)如果update.sh起作用,而新脚本不起作用,那么您可能会遇到一些奇怪的系统配置错误。 尝试升级你的系统和Python; 如果问题依然存在,则可能需要在受影响的系统上进行额外的调试。

    b)如果update.sh和新脚本都工作,那么问题在于调用shell脚本的外部python脚本。 寻找sudosu -sh -lenvos.environ ,其中一个是最可能的罪魁祸首。

    c)如果update.sh和新脚本都没有工作,你的问题很可能是使用ssh客户端配置; 一个典型的原因是你使用的是非默认的身份,没有在~/.ssh/config配置它,而是使用了ssh-add,之后ssh-agent的缓存过期了。 在这种情况下,运行ssh-add identityfile作为你用来认证的身份到git仓库,然后再试一次。

我相信这个答案将帮助你: https : //serverfault.com/questions/497217/automate-git-pull-stuck-with-keychain?answertab=votes#tab-top

我没有使用ssh-agent,它的工作原理:将脚本更改为后面的脚本并尝试。

 #!/bin/bash cd /home/pi/circulation_of_circuits ssh-add /home/yourHomefolderName/.ssh/id_rsa ssh-add -l git pull 

这假定你已经正确配置你的ssh密钥。

看起来像你的版本控制系统,需要对pull的认证,所以可以用pexpect来构建python,

 import pexpect child = pexpect.spawn('./update.sh') child.expect('Password:') child.sendline('SuperSecretPassword') 

尝试使用sh包而不是使用子进程调用。 https://pypi.python.org/pypi/sh我试过这个片段,它为我工作。

 #!/usr/local/bin/python import sh sh.cd("/Users/siyer/workspace/scripts") print sh.git("pull") 

输出:

已经是最新的。

 import subprocess subprocess.call("sh update.sh", shell=True) 

使用Git 1.7.9或更高版本,您可以使用以下凭证助手之一:

超时

 git config --global credential.helper cache 

…它告诉Git保持密码缓存在内存中(默认)15分钟。 您可以设置更长的超时时间:

 git config --global credential.helper "cache --timeout=3600" 

(这个例子是在GitHub的Linux 帮助页面中提出的。)如果需要,您也可以永久存储您的凭证。

无限期地保存

你可以通过git-credential-store来使用

 git config credential.helper store 

GitHub的帮助也表明,如果您使用的是Mac OS X并使用Homebrew来安装Git,则可以使用本机Mac OS X密钥存储:

 git config --global credential.helper osxkeychain 

对于Windows,有一个名为Git Credential Manager for Windows的助手,或者在msysgit中wincred。

 git config --global credential.helper wincred # obsolete 

使用Git for Windows 2.7.3+(2016年3月):

 git config --global credential.helper manager 

对于Linux,您可以使用gnome-keyring(或其他密钥环实现,例如KWallet)。

最后,手动执行一次建议的命令之一后,就可以在不改变脚本的情况下执行脚本。

我可以重现你的错误 。 它与权限无关,它取决于你的ssh如何安装在你的系统上。 要验证这是相同的原因,我需要diff output

将以下内容保存到文件log_shell_env.sh

 #!/bin/bash log="shell_env"$1 echo "create shell_env"$1 echo "shell_env" > $log echo "whoami="$(whoami) >> $log echo "which git="$(which git) >> $log echo "git status="$(git status 2>&1) >> $log echo "git pull="$(git pull 2>&1) >> $log echo "ssh -vT git@github.com="$(ssh -T git@github.com 2>&1) >> $log echo "ssh -V="$(ssh -V 2>&1) >> $log echo "ls -al ~/.ssh="$(ls -a ~/.ssh) >> $log echo "which ssh-askpass="$(which ssh-askpass) >> $log echo "ps -e | grep [s]sh-agent="$(ps -e | grep [s]sh-agent ) >> $log echo "ssh-add -l="$(ssh-add -l) >> $log echo "set=" >> $log set >> $log 

设置执行权限并运行两次
1.从没有参数的控制台
2.从参数'.python'的python脚本
请运行它从相同的Python脚本真的!

  For instance: try: output= subprocess.check_output(['./log_shell_env.sh', '.python'], stderr=subprocess.STDOUT) print(output.decode('utf-8')) except subprocess.CalledProcessError as cpe: print('[ERROR] check_output: %s' % cpe) 

做一个diff shell_env shell_env.python > shell_env.diff生成的shell_env.diff应该显示超过以下差异:

 15,16c15,16 < BASH_ARGC=() < BASH_ARGV=() --- > BASH_ARGC=([0]="1") > BASH_ARGV=([0]=".python") 48c48 < PPID=2209 --- > PPID=2220 72c72 < log=shell_env --- > log=shell_env.python 

回来评论,如果你得到更多的差异更新您的问题与差异输出。

使用下面的python代码。 这将在python中导入os模块,并使用sudo权限进行系统调用。

 #!/bin/python import os os.system("sudo ./update.sh")