【问题标题】:SSH connection not persistentSSH 连接不持久
【发布时间】:2015-07-14 06:25:53
【问题描述】:

我有以下脚本,它通过 SSH 进入网络服务器并执行一些命令,由于某种原因,SSH 连接打开,但在执行命令时它关闭(我认为),因此命令失败并显示如下错误?谁能提供有关如何使 SSH 连接持久的信息?

#!/usr/bin/python
import os
import sys
import json
import fileinput
import pwd
from subprocess import Popen, PIPE, STDOUT
import re
import paramiko
import MySQLdb

resource = r'qca-cdit-01'
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(resource, username='username', password='passwordname')
#chan = ssh.get_transport().open_session()
chan = ssh.invoke_shell()
chan.get_pty()

commandstringlist = \
    ['/local/mnt/workspace/LA_host_builds/AU_LINUX_ANDROID_LA.BF64.1.2.1_RB2.05.01.01.081.031_msm8992',
     'cd frameworks/base',
     'git fetch ssh://cdit@review-android.company.com:29418/platform/frameworks/base refs/changes/21/1260821/2 && git cherry-pick FETCH_HEAD']
for cmd_val in commandstringlist:
    #chan.exec_command(cmd_val)
    chan.send(cmd_val)
    print(chan.recv(1024))

错误:

Traceback (most recent call last):
  File "ssh_test.py", line 21, in <module>
    chan.get_pty()
  File "/usr/local/lib/python2.7/dist-packages/paramiko/channel.py", line 60, in _check
    return func(self, *args, **kwds)
  File "/usr/local/lib/python2.7/dist-packages/paramiko/channel.py", line 177, in get_pty
    self._wait_for_event()
  File "/usr/local/lib/python2.7/dist-packages/paramiko/channel.py", line 1086, in _wait_for_event
    raise e
paramiko.ssh_exception.SSHException: Channel closed

【问题讨论】:

  • 为什么不尝试使用 Ansible 远程执行命令?
  • Ansible 是一个部署工具。它使用 ssh 连接远程机器并执行操作,例如执行自定义命令和脚本、安装软件包等。与 chef 和 puppet 不同,它是无代理的,这意味着您不必在删除机器上安装任何东西,如只要您有 ssh 访问权限。 ansible.com/home
  • @user2125827 :当我从您的代码中删除chan.get_pty()时,它似乎正在工作。

标签: python ssh paramiko


【解决方案1】:

谁能提供有关如何使 SSH 连接持久的信息?

以下是如何通过尝试执行命令然后在发生错误时返回连接然后执行命令来使 SSH 连接持久的示例。

import paramiko

class sshConnection:
  def __init__( self, host, un, pw ):
    self.host = host
    self.un = un
    self.pw = pw

  def connect( self ):
    self.ssh = paramiko.SSHClient()
    self.ssh.load_system_host_keys()
    self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    self.ssh.connect(self.host, username=self.un, password=self.pw)

  def cmd ( self, cmd, tries=0 ):
    self.si, self.so, self.se = None, None, None
    try:
      self.si, self.so, self.se= self.ssh.exec_command(cmd)
    except Exception, e:
      if tries > 3:
        raise
      self.connect( )
      self.cmd(  cmd, tries+1 )
    return self.si, self.so, self.se



conn = sshConnection( "host","username","password" )

si, out, err = conn.cmd("ls -al")
print "\n".join(map ( lambda x: x.strip(), out.readlines()) )

【讨论】:

  • 我希望能够运行连续命令,我试过si, out, err = conn.cmd("cd /local/mnt/workspace/LA_host_builds/AU_LINUX_ANDROID_LA.BF64.1.2.1_RB2.05.01.01.081.031_msm8992") print "\n".join(map ( lambda x: x.strip(), out.readlines()) ) si, out, err = conn.cmd("cd frameworks/base") print "\n".join(map ( lambda x: x.strip(), out.readlines()) ) si, out, err = conn.cmd("git fetch ssh://cdit@review-android.quicinc.com:29418/platform/frameworks/base refs/changes/21/1260821/2 &amp;&amp; git cherry-pick FETCH_HEAD") print "\n".join(map ( lambda x: x.strip(), out.readlines()) )
  • 您遇到了什么样的错误?此代码已经过测试,大部分错误应在收到时提供。
  • 没有错误,只是你的代码不能用于返回命令
  • 背靠背命令应该可以正常工作。您应该检查 stdout 和 stderr 是否有错误。 “cd foo”也会丢失状态,所以更好的方法是 .cmd("cd foo && ls && echo bar")
  • 本次讨论的全部目的是保持状态` "cd foo" and avoid doing cmd("cd foo && ls && echo bar") `
【解决方案2】:

只需做:

#!/usr/bin/python
import os
import sys
import json
import fileinput
import pwd
from subprocess import Popen, PIPE, STDOUT
import re
import paramiko
import MySQLdb

resource = r'qca-cdit-01'
ssh = paramiko.SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(resource, username='username', password='passwordname')
#chan = ssh.get_transport().open_session()
chan = ssh.invoke_shell()

commandstringlist = \
    ['\n/local/mnt/workspace/LA_host_builds/AU_LINUX_ANDROID_LA.BF64.1.2.1_RB2.05.01.01.081.031_msm8992\n',
     '\ncd frameworks/base\n',
     '\ngit fetch ssh://cdit@review-android.company.com:29418/platform/frameworks/base refs/changes/21/1260821/2 && git cherry-pick FETCH_HEAD\n']
for cmd_val in commandstringlist:
    #chan.exec_command(cmd_val)
    chan.send(cmd_val)
    print(chan.recv(8192))

这对我有用。 (你忘了 .send() 不会自动添加行)

【讨论】:

    【解决方案3】:

    诀窍是在执行命令之前切换到目录。您可以轻松地将其集成到您的execute_command

    def execute_command (cmd, pwd=None):
        if pwd:
            cmd = 'cd "%s";%s' % (pwd, cmd)
        print cmd
        si,so,se = ssh.exec_command(cmd) 
        print os.getcwd()
        print "printing so"
        soreadList = so.readlines()
        print soreadList
        print "printing se"
        errList = se.readlines()
        print errList
    

    该命令由远程机器上的 shell 运行,因此也可以添加任何 shell 技巧,如设置环境变量。

    【讨论】:

      【解决方案4】:

      您使用exec_command 执行的每个命令都有自己的通道,因此也有自己的上下文。该上下文包括工作目录。您在一个上下文中更改工作目录,然后尝试在另一个上下文中使用它。相反,对所有命令使用相同的通道。您可以打开一个通道并使用它,也可以一次发出所有命令。

      commandstringlist = ['cd /local/mnt/workspace/test2 && cd data/log && git fetch ssh://username@review-android.company.com:29418/platform/data/log refs/changes/21/1260821/2 && git cherry-pick FETCH_HEAD']
      

      这里还有一些其他问题应该更详细地解释这一点。

      https://unix.stackexchange.com/questions/80821/why-does-cd-command-not-work-via-ssh https://superuser.com/questions/46851/keeping-working-directory-across-ssh https://stackoverflow.com/a/6770272/492773

      【讨论】:

      • 正在寻找一种打开 ssh 连接并且我可以灵活地独立运行多个命令的方式...
      • 您可以运行任意数量的命令。连接不会关闭,只会关闭通道。将cd 添加到您运行的每个命令将是最简单的解决方案。您还可以打开一个频道或使用invoke_shell() 来获得与从命令行使用ssh 时完全相同的功能。
      • 我不清楚你说Adding cd to each command you run would be the simplest solution,你能解释一下吗?另外,你能举个例子You can also open a channel or use invoke_shell() to get the exact same features
      • 看看我发布的新commandstringlist。它有 ['cd ... &amp;&amp; command'] 而不是 ['cd ...', 'command']
      • @kichikk - 问题是不是这些命令,一旦 ssh 连接打开,我有很多命令要执行,很难继续添加&amp;&amp;
      猜你喜欢
      • 2013-04-04
      • 1970-01-01
      • 1970-01-01
      • 2017-07-12
      • 2011-03-29
      • 2011-01-16
      • 2013-01-22
      • 2012-12-05
      • 1970-01-01
      相关资源
      最近更新 更多