2017-03-05 386 views
15

我拥有最简单的脚本调用update.sh运行shell脚本

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

当我把这个从终端与./update.sh我得到已经起床了最新或者更新文件像预期一样。

我也有一个Python脚本,里面那个素文字是:

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

当调用同一个脚本,我得到:

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

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

(我使用SSH)。

-----------------更新--------------------

其他人有一个找我:

好吧,这样有些进步。当我启动映像时,我无法在 的repo目录中运行git pull,并且bash脚本也失败。它似乎是 ,因为bitbucket存储库是私人的,需要认证 拉(我使用的是公开的,这就是为什么我没有 问题)。大概git在第一个输入 之后记得这个,bash不知何故会让git认为你随后输入了 命令,但是从python运行它并不相同。

我不是git专家,但必须有一些方法来设置这个,所以 python可以提供身份验证。

+0

这是否解决您的问题(传递'壳=真'标志):http://stackoverflow.com/a/325474/608259 – kalaracey

+0

没有,万一它的事项我把它叫做这样'CMD = [ '/home/pi/circulation_of_circuits/update.sh'] \t \t过程= subprocess.Popen(CMD,壳=真,标准输出= subprocess.PIPE) \t \t process.wait()' – clankill3r

+0

如果有人想知道, 'os.geteuid()'给出一个0,所以应该是好的。 – clankill3r

回答

11

听起来像你需要给你的ssh命令公共或私有密钥也可以或许访问:

ssh -i /backup/home/user/.ssh/id_dsa [email protected] 

-i告诉它在哪里寻找关键

3

好像你的版本控制系统,需要认证的pull这样可以建立与使用pexpect蟒蛇,

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

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

#!/usr/local/bin/python 

import sh 

sh.cd("/Users/siyer/workspace/scripts") 
print sh.git("pull") 

输出:

已经跟上时代的。

5

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

由于该问题仅在通过另一个脚本运行时才会显现,因此很可能是由与环境变量混淆造成的。 Subprocess.call应该按原样传递环境,所以有几个常见的嫌疑人:

  1. sudo。
    • 如果你正在使用sudo,它会通过一个几乎为空的环境,过程
  2. 的python脚本本身
    • 如果python脚本改变它的包膜,这些变化将得到传播到子过程也是如此。
  3. sh -lsu -
    • 这些命令设置一个登录外壳,这意味着它们的环境被重置为默认值。

所有的这些原因可以隐藏的环境变量的ssh-agent(或其他一些重要的管理工具)可能需要工作。

步骤来诊断和修复:

  1. 隔离问题。

    • 创建一个最小的python脚本,除了运行subprocess.call(['./update.sh'])以外别无其他。运行update.sh和新脚本。
  2. 诊断问题,并据此定出:

    a)如果update.sh工作,而新的脚本不,你可能遇到系统错误配置的一些奇怪的极端情况。尝试升级你的系统和Python;如果问题依然存在,则可能需要对受影响的系统本身进行额外的调试。 b)如果update.sh和新脚本都工作,那么问题在于调用shell脚本的外部python脚本。寻找发生的sudo,su -,sh -l,envos.environ,其中之一是最有可能的罪魁祸首。

    c)如果update.sh和新脚本都不起作用,那么您的问题可能与ssh客户端配置有关;一个典型的原因是您使用的是非默认身份,没有在~/.ssh/config中配置它,而是使用了ssh-add,之后,ssh-agent的缓存过期。在这种情况下,运行ssh-add identityfile获取您用于验证该git仓库的标识,然后重试。

1

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

将下列内容保存到一个文件​​,

#!/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 [email protected]="$(ssh -T [email protected] 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 

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

2
import subprocess 

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

尽管此代码可能会回答这个问题,但提供关于此代码为何和/或如何回答问题的其他上下文可提高其长期价值。 –

+0

我已经添加了“sh update.sh”,因为我们可以用两种方式执行shell脚本,即1)./update.sh和2)sh update.sh,这里两者都应该工作。但对他来说,一个人工作,所以我被建议他尝试一个。谢谢 –

+0

您可以[编辑]您的答案以包含更多信息。 –

1

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

一个超时

git config --global credential.helper cache 

...它告诉混帐保持您的密码缓存在内存中(默认)15分钟。您可以设置一个较长的超时:

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

(即例如建议在GitHub help page的Linux版本。)您还可以永久如果需要保存您的凭据。

无限期

保存您可以使用git-credential-store通过

git config credential.helper store 

GitHub's help还建议,如果你在Mac OS X和使用自制软件安装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的Windows 2.7.3+(2016年3月):

git config --global credential.helper manager 

对于Linux,你可以使用GNOME的钥匙圈(或其他钥匙圈实现诸如KDE钱包)。

最后,手动执行一次建议的命令之一后,您可以执行脚本而不更改它。

+0

@ clankill3r你试过我的建议吗?如果您的问题得到良好记录,对我们所有人都将是有益的 – sdikby

1

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

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

如果他们想要使用非root用户,会发生什么情况?或者他们想在不输入密码的情况下做到这一点? – tahsmith

+0

如果用户不是root用户,那么他们必须至少成为sudo组的成员。 shell脚本还必​​须具有sudo组的可执行权限,否则'sudo bash update.sh'就足够了。有些方法可以在不输入密码的情况下执行此操作,但它们有风险,我建议不要这样做。 –