【问题标题】:Run shell script from python with permissions使用权限从 python 运行 shell 脚本
【发布时间】:2017-07-25 16:35:30
【问题描述】:

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

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

当我从终端使用./update.sh 调用它时,我得到一个已经是最新的,或者它会像预期的那样更新文件。

我还有一个 python 脚本,里面的 scipt 是:

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

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

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

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

(我使用 SSH)。

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

别人找过我:

好的,所以有些进展。当我启动你的图像时,我无法运行 git pull in 您的 repo 目录和 bash 脚本也失败了。好像是 因为 bitbucket 存储库是私有的并且需要身份验证 对于拉(我使用的是公开的,所以这就是为什么我没有 问题)。大概 git 在你第一次输入之后会记住这一点 时间,bash 以某种方式欺骗 git 认为是你在输入 随后的命令,但从 python 运行它是不一样的。

我不是 git 专家,但必须有某种设置方法 python可以提供认证。

【问题讨论】:

  • 这是否解决了您的问题(通过shell=true 标志):stackoverflow.com/a/325474/608259
  • 不,以防万一我这样称呼它cmd = ['/home/pi/circulation_of_circuits/update.sh'] process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE) process.wait()
  • 如果有人想知道,os.geteuid() 会给出一个 0,这样应该很好。
  • Permission denied (publickey). 表明你的 ssh 配置有问题,用不同的用户运行 python 脚本?
  • 也许您可以尝试cmd=['sudo', '-u', 'yourusername', 'path to your bash', '/home/pi/circulation_of_circuits/update.sh'] 之类的方法,看看是否有帮助?这将使用您自己的用户权限而不是 sudo 运行脚本,因为 kennytm 的评论指出您应该以 root 身份运行来执行 git pull。

标签: python linux git shell


【解决方案1】:

相信这个答案会对你有所帮助: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 密钥。

【讨论】:

  • 你可能还需要在 ssh-add 之前使用 ``` eval ssh-agent -s `` 启动你的 ssh-agent
【解决方案2】:

听起来你需要给你的 ssh 命令一个它可能可以访问的公钥或私钥:

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

-i 告诉它在哪里寻找密钥

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      尝试使用 sh 包而不是使用子进程调用。 https://pypi.python.org/pypi/sh 我尝试了这个 sn-p,它对我有用。

      #!/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,它将向进程传递一个大部分为空的环境
        2. python 脚本本身
          • 如果 python 脚本更改了它的环境,这些更改也会传播到子进程。
        3. sh -lsu -
          • 这些命令设置了一个登录 shell,这意味着它们的环境被重置为默认值。

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

        诊断和修复步骤:

        1. 隔离问题。

          • 创建一个除了运行subprocess.call(['./update.sh'])之外什么都不做的最小python脚本。运行 update.sh 和新脚本。
        2. 诊断问题并进行相应的修复:

          a) 如果 update.sh 有效,而新脚本无效,则您可能遇到了一些奇怪的系统配置错误的极端情况。尝试升级你的系统和python;如果问题仍然存在,则可能需要对受影响的系统本身进行额外的调试。

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

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

        【讨论】:

          【解决方案6】:

          我可以重现你的错误。它与权限无关,这取决于您的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
          

          如果您得到更多差异,请回来发表评论 使用差异输出更新您的问题。

          【讨论】:

            【解决方案7】:
            import subprocess 
            
            subprocess.call("sh update.sh", shell=True)
            

            【讨论】:

            • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
            • 我添加了 "sh update.sh" ,因为我们可以通过两种方式执行 shell 脚本,即 1) ./update.sh 和 2) sh update.sh ,这两者都应该工作。但对他来说 1 是有效的,所以我被建议他尝试 2 一个。谢谢
            • 您可以edit您的答案以包含更多信息。
            【解决方案8】:

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

            超时

            git config --global credential.helper cache
            

            ... 它告诉 Git 将您的密码缓存在内存中(默认情况下)15 分钟。您可以设置更长的超时时间:

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

            (该示例在 Linux 的 GitHub help page 中提出。)如果需要,您还可以永久存储您的凭据。

            无限期保存

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

            git config credential.helper store
            

            GitHub's help 还建议,如果您在 Mac OS X 上并使用 Homebrew 安装 Git,您可以使用原生 Mac OS X 密钥库:

            git config --global credential.helper osxkeychain
            

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

            git config --global credential.helper wincred # obsolete
            

            使用适用于 Windows 2.7.3+ 的 Git(2016 年 3 月):

            git config --global credential.helper manager
            

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

            最后,在手动执行一次建议的命令后,您可以执行脚本而无需对其进行更改。

            【讨论】:

            • @clankill3r 你试过我的建议了吗?如果您的问题得到妥善记录,这对我们所有人都有好处
            【解决方案9】:

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

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

            【讨论】:

            • 如果他们想使用非 root 用户会发生什么?或者他们想在不输入密码的情况下执行此操作?
            • 如果用户不是 root,那么他们至少必须是 sudo 组的成员。 shell 脚本还必须具有 sudo 组的可执行权限,否则 sudo bash update.sh 就足够了。有一些方法可以在不输入密码的情况下执行此操作,但是它们有风险,我建议不要这样做。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-12-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多