首页 文章

如何使用paramiko保持ssh会话未过期?

提问于
浏览
8

我打算使用paramiko在远程主机上运行几个命令,但运行命令后ssh会话关闭 .
下面列出的代码:

from paramiko import SSHClient  
import paramiko  
ssh = SSHClient()
ssh.load_system_host_keys()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(host, 22, user, passwd, timeout=3)
stdin, stdout, stderr = ssh.exec_command('uname -a')

那么有什么方法可以阻止ssh会话结束?或帕拉米科的任何替代品?

Update
当连接到Linux服务器时,我能够在我的Macbook上保持调用 exec_command ,但是当连接到 switch 时,ssh会话在Linux服务器上自动关闭 exec_command 并且
SSHException: paramiko.ssh_exception.SSHException: SSH session not active

>>> print ssh.get_transport()  
>>> <paramiko.Transport at 0xf00216d0L (unconnected)>  
>>> print ssh.get_transport().is_active()  
>>> False  
>>> print ssh.get_transport().is_authenticated()  
>>> False

是否有任何方法可以让paramiko ssh会话始终保持活动状态?

paramiko调试模式信息返回如下:

启动线程(客户端模式):0x2657e10L连接(版本1.99,客户端Comware-5.20)kex algos:[u'diffie-hellman-group-exchange-sha1',u'diffie-hellman-group14-sha1',u'diffie -hellman-group1-sha1']服务器密钥:[u'ssh-rsa']客户端加密:[u'aes128-cbc',u'3des-cbc',u'des-cbc']服务器加密:[u' aes128-cbc',u'3des-cbc',u'des-cbc']客户端mac:[u'hmac-sha1',u'hmac-sha1-96',u'hmac-md5',u'hmac- md5-96']服务器mac:[u'hmac-sha1',u'hmac-sha1-96',u'hmac-md5',u'hmac-md5-96']客户端压缩:[u'none']服务器压缩:[u'none']客户端lang:[u'']服务器lang:[u''] kex跟随?False Ciphers同意:local = aes128-cbc,remote = aes128-cbc using kex diffie-hellman-group14 -sha1;服务器密钥类型ssh-rsa;密码:本地aes128-cbc,远程aes128-cbc; mac:local hmac-sha1,remote hmac-sha1;压缩:本地无,远程无切换到新密钥... userauth可以认证(密码)成功! [chan 0]最大数据包:32768字节[chan 1]最大数据包:32768字节[chan 0]最大数据包输出:32496字节Secsh通道0打开 . Secsh channel 2 open FAILED:资源不足:资源不足[chan 0] Sesch channel 0 request ok [chan 0] EOF sent(0)

2 回答

  • 2

    您可以使用paramiko实现交互式shell,这样在远程shell上执行命令后通道不会关闭 .

    import paramiko
    import re
    
    
    class ShellHandler:
    
        def __init__(self, host, user, psw):
            self.ssh = paramiko.SSHClient()
            self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
            self.ssh.connect(host, username=user, password=psw, port=22)
    
            channel = self.ssh.invoke_shell()
            self.stdin = channel.makefile('wb')
            self.stdout = channel.makefile('r')
    
        def __del__(self):
            self.ssh.close()
    
        @staticmethod
        def _print_exec_out(cmd, out_buf, err_buf, exit_status):
            print('command executed: {}'.format(cmd))
            print('STDOUT:')
            for line in out_buf:
                print(line, end="")
            print('end of STDOUT')
            print('STDERR:')
            for line in err_buf:
                print(line, end="")
            print('end of STDERR')
            print('finished with exit status: {}'.format(exit_status))
            print('------------------------------------')
            pass
    
        def execute(self, cmd):
            """
    
            :param cmd: the command to be executed on the remote computer
            :examples:  execute('ls')
                        execute('finger')
                        execute('cd folder_name')
            """
            cmd = cmd.strip('\n')
            self.stdin.write(cmd + '\n')
            finish = 'end of stdOUT buffer. finished with exit status'
            echo_cmd = 'echo {} $?'.format(finish)
            self.stdin.write(echo_cmd + '\n')
            shin = self.stdin
            self.stdin.flush()
    
            shout = []
            sherr = []
            exit_status = 0
            for line in self.stdout:
                if str(line).startswith(cmd) or str(line).startswith(echo_cmd):
                    # up for now filled with shell junk from stdin
                    shout = []
                elif str(line).startswith(finish):
                    # our finish command ends with the exit status
                    exit_status = int(str(line).rsplit(maxsplit=1)[1])
                    if exit_status:
                        # stderr is combined with stdout.
                        # thus, swap sherr with shout in a case of failure.
                        sherr = shout
                        shout = []
                    break
                else:
                    # get rid of 'coloring and formatting' special characters
                    shout.append(re.compile(r'(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]').sub('', line).
                                 replace('\b', '').replace('\r', ''))
    
            # first and last lines of shout/sherr contain a prompt
            if shout and echo_cmd in shout[-1]:
                shout.pop()
            if shout and cmd in shout[0]:
                shout.pop(0)
            if sherr and echo_cmd in sherr[-1]:
                sherr.pop()
            if sherr and cmd in sherr[0]:
                sherr.pop(0)
    
            self._print_exec_out(cmd=cmd, out_buf=shout, err_buf=sherr, exit_status=exit_status)
            return shin, shout, sherr
    
  • 3

    我看到你在连接调用中使用了 timeout 参数:

    ssh.connect(host, 22, user, passwd, timeout=3)
    

    从文档:

    timeout(float) - TCP连接的可选超时(以秒为单位)

    在我的一个脚本中,我只是这样做:

    ssh = paramiko.SSHClient()
    ssh.connect(host, username=settings.user)
    

    这使得连接保持打开状态直到我打电话

    ssh.close()
    

相关问题