【问题标题】:Subprocess on remote server远程服务器上的子进程
【发布时间】:2015-10-07 05:45:36
【问题描述】:

我正在使用此代码在远程服务器上执行命令。

import subprocess
import sys
COMMAND="ls"

ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND],
                   shell=False,
                   stdout=subprocess.PIPE,
                   stderr=subprocess.PIPE)
result = ssh.stdout.readlines()
if result == []:
    error = ssh.stderr.readlines()
    print >>sys.stderr, "ERROR: %s" % error
else:
    print result

当我尝试执行此脚本时,我会提示输入密码。有什么办法可以避免它,例如,我可以以某种方式在脚本中输入密码吗?此外,密码应该以某种方式加密,以便有权访问脚本的人看不到它。

【问题讨论】:

  • 您是否考虑过使用密码输入以外的身份验证方案?

标签: python ssh command subprocess


【解决方案1】:

一种方法是创建一个公钥,将它放在服务器上,然后像这样使用ssh -i /path/to/pub/key user@host 或使用paramiko

import paramiko
import getpass

ssh = paramiko.SSHClient()

ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

p = getpass.getpass()

ssh.connect('hostname', username='user', password=p)

stdin, stdout, stderr = ssh.exec_command('ls')
print stdout.readlines()
ssh.close()

【讨论】:

  • tnx.有什么办法可以屏蔽密码吗?
  • @ZvonimirPeran 是的,给我一秒钟修改我的答案
  • @ZvonimirPeran 现在检查,这适用于大多数终端版本,getpass 会在某些终端上发出警告,提示它无法隐藏密码
【解决方案2】:

为什么要这么复杂?这是我的建议:

1) 在 ~/.ssh/config 文件中创建一个 ssh 配置部分:

Host myserver
  HostName 50.50.50.12 (fill in with your server's ip)
  Port xxxx (optional)
  User me (your username for server)

2) 如果您已经生成了 ssh 密钥对,请立即执行(使用 ssh-keygen)。然后上传:

$ ssh-copy-id myserver

3) 现在您可以将子进程与 ssh 一起使用。例如,为了捕获输出,我调用:

result = subprocess.check_output(['ssh', 'myserver', 'cat', 'somefile'])

简单、健壮且唯一需要密码的时候就是将公钥复制到服务器时。

顺便说一句,使用这些步骤,您的代码可能也可以正常工作。

【讨论】:

  • 这是一个绝妙的答案。我给了你一个大拇指:)
【解决方案3】:

你应该使用pexpectparamiko连接到远程机器,然后生成一个孩子,然后运行subprocess来实现你想要的。

【讨论】:

    【解决方案4】:

    这是我之前遇到此问题时所做的:

    1. 设置您的 ssh 密钥以访问服务器。
    2. Set up an alias for the server you're accessing。下面我就叫它remote_server
    3. 将以下两行放在~/.bash_profile的末尾。

      eval $(ssh-agent -s)
      ssh-add
      

    现在每次启动 shell 时,系统都会提示您输入密码。通过输入它,您将验证您的 ssh 密钥并在您的 bash 会话开始时将它们“放在手边”。在接下来的会话中,您将能够运行类似的命令

        ssh remote_server ls
    

    无需提示输入密码。这里ls 将在远程服务器上运行并将结果返回给您。同样,如果您从 shell 执行,您的 python 脚本应该在没有密码提示中断的情况下运行。

    您还可以通过键入 ssh remote_server 来 ssh 到服务器,而无需每次都输入您的用户名或密码。

    这样做的好处是,无论如何您都应该这样做以避免密码烦恼和记住时髦的服务器名称:) 此外,您不必担心将密码保存在脚本中的任何位置。唯一潜在的缺点是,如果您想与其他人共享 python 脚本,他们也必须进行此配置(无论如何他们都应该这样做)。

    【讨论】:

      【解决方案5】:

      你真的不需要像 pexpect 这样的东西来处理这个问题。 SSH 密钥已经为此类问题提供了非常好的和安全的解决方案。

      获得所需结果的最简单方法可能是生成一个 ssh 密钥并将其放在设备的 .ssh 文件夹中。我相信 github 有一个很好的指南来做这件事,如果你研究一下的话。在两个系统上正确设置密钥后,您实际上不必在代码中添加一行。当您不指定密码时,它会自动使用密钥对您进行身份验证。

      【讨论】:

        【解决方案6】:

        虽然subprocess.Popen 可能适用于包装ssh 访问,但这不是这样做的首选方式。

        我推荐使用paramiko

        import paramiko
        ssh_client = paramiko.SSHClient()
        ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh_client.connect(server, username=user,password=password)
        ...
        ssh_client.close()
        

        如果你想模拟一个终端,就好像用户在打字一样:

        chan=ssh_client.invoke_shell()
        
        def exec_cmd(cmd):
            """Gets ssh command(s), execute them, and returns the output"""
            prompt='bash $' # the command line prompt in the ssh terminal
            buff=''
            chan.send(str(cmd)+'\n')
            while not chan.recv_ready():
                time.sleep(1)
            while not buff.endswith(prompt):
                buff+=ssh_client.chan.recv(1024)
            return buff[:len(prompt)]
        

        用法示例:exec_cmd('pwd')

        如果事先不知道提示,可以这样设置:

        chan.send('PS1="python-ssh:"\n')
        

        【讨论】:

        • paramiko 可能太低级,无法通过 ssh 运行命令。在这里使用fabricpexpect 更容易。无论如何,正确的解决方案都会使用 ssh 密钥。
        • 是的,ssh 密钥是肯定的,除非出于某种原因不需要这样做。
        【解决方案7】:

        你可以使用以下。

        import subprocess
        import sys
        COMMAND="ls"
        
        ssh = subprocess.Popen("powershell putty.exe user@HOST -pw "password", stdout=PIPE, stdin=PIPE, stderr=STDOUT)
        result = ssh.stdout.readlines()
        if result == []:
            error = ssh.stderr.readlines()
            print >>sys.stderr, "ERROR: %s" % error
        else:
            print result
        

        【讨论】:

        猜你喜欢
        • 2019-03-06
        • 2011-07-21
        • 2017-04-03
        • 2020-01-29
        • 1970-01-01
        • 1970-01-01
        • 2014-06-01
        • 1970-01-01
        • 2020-10-23
        相关资源
        最近更新 更多