Python 远程服务器上的子进程

Python 远程服务器上的子进程,python,ssh,command,subprocess,Python,Ssh,Command,Subprocess,我使用这段代码在远程服务器上执行命令 import subprocess import sys COMMAND="ls" ssh = subprocess.Popen(["ssh", "%s" % HOST, COMMAND], shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE) result = ssh.std

我使用这段代码在远程服务器上执行命令

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

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

您应该使用
pexpect
paramiko
连接到远程机器,然后生成一个子进程,然后运行
子进程
来实现您想要的功能。

一种方法是创建公钥,将其放在服务器上,和do
ssh-i/path/to/pub/keyuser@host
或像这样使用:

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()

虽然
subprocess.Popen
可以用于包装
ssh
访问,但这不是首选的方法

我建议使用

如果要模拟终端,就像用户在键入:

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\u cmd('pwd')

如果您事先不知道提示,可以将其设置为:

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

以下是我以前遇到这个问题时所做的:

  • 设置ssh密钥以访问服务器
  • 。下面我将它称为
    remote\u server
  • 将以下两行放在
    ~/.bash\u profile
    的末尾

    eval $(ssh-agent -s)
    ssh-add
    
  • 现在,每次启动shell时,都会提示您输入密码短语。通过输入它,您将对ssh密钥进行身份验证,并在bash会话开始时将它们“放在手中”。在剩下的会话中,您将能够运行如下命令

        ssh remote_server ls
    
    没有提示输入密码短语。此处
    ls
    将在远程服务器上运行,并将结果返回给您。同样,如果您从shell执行python脚本,那么它应该在不中断密码提示的情况下运行

    您还可以通过键入
    ssh remote\u server
    以ssh方式连接到服务器,而无需每次输入用户名或密码


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

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


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

    为什么要把它弄得这么复杂?以下是我的建议:

    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'])
    
    简单、可靠,而且只需要在将公钥复制到服务器时使用密码


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

    您可以使用以下步骤

    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
    

    tnx。有办法屏蔽密码吗?@ZvonimirPeran是的,给我一点时间修改我的密码answer@ZvonimirPeran现在检查,这适用于大多数终端版本,
    getpass
    将在某些终端上发出警告,它无法隐藏密码。您是否考虑过使用密码输入以外的身份验证方案?
    paramiko
    的级别可能太低,无法通过ssh运行命令。在这里更容易使用。正确的解决方案将使用ssh密钥。是的,ssh密钥是肯定的,除非出于某种原因不需要。这是一个简单的答案。我向你竖起大拇指:)你能展示一下你的代码片段是如何试图回答这个问题的吗?还有,请跟我来
    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