【问题标题】:python paramiko sshpython paramiko ssh
【发布时间】:2012-05-31 11:43:32
【问题描述】:

我是 python 新手。我写了一个脚本来连接主机并执行一个命令

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, username=user, password=pw)

print 'running remote command'

stdin, stdout, stderr = ssh.exec_command(command)
stdin.close()

for line in stdout.read().splitlines():
    print '%s$: %s' % (host, line)
    if outfile != None:
        f_outfile.write("%s\n" %line)

for line in stderr.read().splitlines():
    print '%s$: %s' % (host, line + "\n")
    if outfile != None:
        f_outfile.write("%s\n" %line)

ssh.close()

if outfile != None:
    f_outfile.close()

print 'connection to %s closed' %host

except:
   e = sys.exc_info()[1]
   print '%s' %e

当远程命令不需要 tty 时工作正常。我找到了一个 invoke_shell 示例Nested SSH session with Paramiko。我对此解决方案不满意,因为如果服务器的提示未在我的脚本中指定-> 无限循环或脚本中指定的提示是返回文本中的字符串-> 并非所有数据都将被接收.有没有更好的解决方案,比如在我的脚本中将 stdout 和 stderr 发回?

【问题讨论】:

  • 请注意,此答案不使用 SSH 密钥,因此需要密码。使用 SSH 密钥,您不需要 pw,而是传递 key_filename 参数。

标签: python ssh paramiko


【解决方案1】:

接受的答案有问题,它有时(随机)会从服务器带来剪裁的响应。我不知道为什么,我没有调查接受答案的错误原因,因为这段代码非常适合我:

import paramiko

ip='server ip'
port=22
username='username'
password='password'

cmd='some useful command' 

ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip,port,username,password)

stdin,stdout,stderr=ssh.exec_command(cmd)
outlines=stdout.readlines()
resp=''.join(outlines)
print(resp)

stdin,stdout,stderr=ssh.exec_command('some really useful command')
outlines=stdout.readlines()
resp=''.join(outlines)
print(resp)

【讨论】:

  • 我也看到了,这就像一个带有 exit_status_ready() 和 recv_ready() 的竞争条件
  • 以防万一有人希望使用上述方法捕获退出代码 - stdout.channel.recv_exit_status()
  • 有一个异常:key不能用于签名
【解决方案2】:

您可以在以下位置找到大量 paramiko API 文档:http://docs.paramiko.org/en/stable/index.html

我使用以下方法在受密码保护的客户端上执行命令:

import paramiko

nbytes = 4096
hostname = 'hostname'
port = 22
username = 'username' 
password = 'password'
command = 'ls'

client = paramiko.Transport((hostname, port))
client.connect(username=username, password=password)

stdout_data = []
stderr_data = []
session = client.open_channel(kind='session')
session.exec_command(command)
while True:
    if session.recv_ready():
        stdout_data.append(session.recv(nbytes))
    if session.recv_stderr_ready():
        stderr_data.append(session.recv_stderr(nbytes))
    if session.exit_status_ready():
        break

print 'exit status: ', session.recv_exit_status()
print ''.join(stdout_data)
print ''.join(stderr_data)

session.close()
client.close()

【讨论】:

  • 例如应该使用session.recv(4096)session.recv_stderr(4096) 而不是data_blockdata_block 是从哪里来的?)。
  • 你是对的,data_block 和你描述的一样(recv/recv_stderr)但是我不小心删除了这些行。
  • 截至 2015 年 5 月,Paramiko 文档为 here
  • 截至 2015 年 12 月,Paramiko 文档(版本 1.16)在这里:docs.paramiko.org/en/1.16/index.html
  • 这段代码有问题:它可以工作,但有时响应不完整。
【解决方案3】:

@ThePracticalOne 的代码非常适合展示用法,除了一件事: 有时输出会不完整。(if session.recv_ready(): 之后session.recv_ready() 变为真,而session.recv_stderr_ready()session.exit_status_ready() 在进入下一个循环之前变为真)

所以我的想法是在准备好退出会话时检索数据。

while True:
if session.exit_status_ready():
while True:
    while True:
        print "try to recv stdout..."
        ret = session.recv(nbytes)
        if len(ret) == 0:
            break
        stdout_data.append(ret)

    while True:
        print "try to recv stderr..."
        ret = session.recv_stderr(nbytes)
        if len(ret) == 0:
            break
        stderr_data.append(ret)
    break

【讨论】:

    【解决方案4】:

    无密码 SSH 对我有用

    import paramiko
    
    def connect_SSH():
        ssh = paramiko.SSHClient()
        username = '<uname>'
        port = <port-no>
        ip = '<ip-address>'
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(ip,port,username)
    
        stdin, stdout, stderr = ssh.exec_command('<cmd>')
        outlines = stdout.readlines()
        resp=''.join(outlines)
        print(resp) 
    connect_SSH()
    

    【讨论】:

      【解决方案5】:
      ###### Use paramiko to connect to LINUX platform############
      import paramiko
      
      ip='server ip'
      port=22
      username='username'
      password='password'
      ssh=paramiko.SSHClient()
      ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      ssh.connect(ip,port,username,password)
      
      --------Connection Established-----------------------------
      
      ######To run shell commands on remote connection###########
      import paramiko
      
      ip='server ip'
      port=22
      username='username'
      password='password'
      ssh=paramiko.SSHClient()
      ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
      ssh.connect(ip,port,username,password)
      
      
      stdin,stdout,stderr=ssh.exec_command(cmd)
      outlines=stdout.readlines()
      resp=''.join(outlines)
      print(resp) # Output 
      
      猜你喜欢
      • 2013-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-07
      • 2022-01-08
      • 1970-01-01
      相关资源
      最近更新 更多