繁体   English   中英

Python在同一会话中运行多个ssh命令

[英]Python run mutiple ssh commands in the same session

我的目标是使用python连接到SSH并通过Paramiko或Fabric进行身份验证。 但是我想在每次执行后保持会话打开并读取输入/输出。 使用paramiko,我只能在会话关闭之前运行1条命令,并且要求我再次进行身份验证并且会话挂起。 而且由于fabric使用paramiko库,它给了我同样的问题。 例如,如果我的目录结构是这样的

-家

--myfolder1

--myfolder2

由于会话关闭,我想执行以下命令而无需重新进行身份验证。

(make connection)
run cmd: 'pwd'
output: /home
run cmd: 'cd myfolder2'
run cmd: 'pwd'
output: /home/myfolder2

现在有任何模块可以做到这一点吗? 可以使用原生python从头开始制作吗? 而且这就是不可能...吗?

编辑添加的代码。 没有新的open_session,它将关闭,并且我无法运行任何命令。 使用此命令运行第一个命令后,将再次提示我进行身份验证,并创建一个无限循环。

Edit2如果在每个命令之后关闭,那么这根本不可能正确吗?

edit3如果我在其他服务器上使用paramikio.SSHClient在exec_command上运行它,它不会要求我重新进行身份验证,但是如果我先“ cd somedir”然后“ pwd”,它将输出我返回创建位置的根目录。

class connect:

    newconnection = ''

    def __init__(self,username,password): 
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        try:
            ssh.connect('someserver', username=username,password=password,port=22,timeout=5)
        except:
            print "Count not connect"
            sys.exit()
        self.newconnection = ssh

    def con(self):
        return self.newconnection


#This will create the connection
sshconnection = connect('someuser','somepassword').con()

while True:
    cmd = raw_input("Command to run: ")
    if cmd == "":
        break
    try:
        transport = sshconnection.get_transport()
        transport.set_keepalive(999999)
        chan = transport.open_session() 
        chan.settimeout(3)
        chan.setblocking(0)
    except:
        print "Failed to open a channel"
        chan.get_exception()
        sys.exit()

    print "running '%s'" % cmd
    stdout_data = []
    stderr_data = []
    pprint.pprint(chan)
    nbytes = 4096
    chan.settimeout(5)
    chan.get_pty()
    chan.exec_command(cmd)
    while True:
        print "Inside loop " , chan.exit_status_ready()
        time.sleep(1.2)
        if chan.recv_ready():
            print "First if"
            stdout_data.append(chan.recv(nbytes))
        if chan.recv_stderr_ready():
            print "Recv Ready"
            stderr_data.append(chan.recv_stderr(nbytes))
        if chan.exit_status_ready():
            print "Breaking"
            break

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

当您可以将命令串联为一个模块时,可以通过使用常规模块来实现。 尝试

pwd ; cd myfolder2 ; pwd

作为命令。 这应该可以工作,但是当您有需要参数的更复杂的命令时,很快就会变得乏味,而当参数包含空格时,这将变得很糟糕。 然后,下一步是将包含所有命令的脚本复制到远程端,并告诉ssh执行所述脚本。

这种方法的另一个问题是SSH在所有命令执行完毕后才返回。

或者,您可以构建“命令服务器”,即侦听传入连接并执行发送给它的命令的简单TCP服务器。 编写起来很简单,但是也很不安全。 同样,解决方案是将服务器转换为(Python)脚本,该脚本从stdin读取命令,然后通过SSH远程启动该脚本,然后发送命令。

暂无
暂无

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

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