简体   繁体   English

SSH连接不持久

[英]SSH connection not persistent

I have the following script which SSH's into a network server and executes some commands, for some reason the SSH connection opens but by the time the commands are executed it closes (I think), as a result the commands are failing with below error? 我有以下脚本,它通过SSH进入网络服务器并执行一些命令,由于某些原因,SSH连接会打开,但是在执行命令时它会关闭(我认为),结果命令失败并出现以下错误? Can anyone provide info how to make the SSH connection persistent? 谁能提供有关如何使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))

error: 错误:

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

Every command you execute using exec_command has a channel of its own and therefore a context of its own. 您使用exec_command执行的每个命令都有其自己的通道,因此具有自己的上下文。 That context includes the working directory. 该上下文包括工作目录。 You change the working directory in one context and then try to use it in another. 您在一个上下文中更改工作目录,然后尝试在另一个上下文中使用它。 Instead, use the same channel for all the commands. 而是,对所有命令使用相同的通道。 You can either open a channel and use it, or just issue all the commands at once. 您可以打开一个通道并使用它,也可以一次发出所有命令。

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']

Here are a few other questions that should explain this in more detail. 以下是一些其他问题,应该对此做更详细的说明。

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

The trick is to change to the directory before executing the command. 诀窍是在执行命令之前切换到目录。 You can easily integrate it into your execute_command : 您可以轻松地将其集成到您的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

The command is run by a shell on the remote machine, so any shell tricks like setting environment variables could be added also. 该命令由远程计算机上的外壳程序运行,因此还可以添加任何外壳程序技巧,例如设置环境变量。

Can anyone provide info how to make the SSH connection persistent? 谁能提供有关如何使SSH连接持久化的信息?

The following is an example of how to make an SSH connection persistent by attempting to execute a command and then falling back on connecting then executing the command when errors occur. 以下是一个示例,该示例说明了如何通过尝试执行命令,然后退回到连接状态,然后在发生错误时执行命令来保持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()) )

Simply do : 只需:

#!/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))

which worked for me. 对我有用。 (You forgot .send() doesn't add lines automatically) (您忘记了.send()不会自动添加行)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM