Python paramiko脚本,exec_command()时读取输出问题

11 投票
5 回答
48545 浏览
提问于 2025-04-17 03:49

背景

我正在使用Python和Paramiko来自动化我每次在课堂上提交程序时的流程。我们使用一个叫“handin”的命令来提交源代码,但这个操作必须在学校的电脑上进行。所以当我在家提交代码时,我需要:通过sftp连接到学校的服务器,把文件放到一个目录里,然后ssh连接到学校的电脑上,使用'handin'命令。

我可以成功地把文件放到学校的机器上。但是当我尝试使用exec_command('handin my files')并读取输出以决定下一步操作时,就出现了问题。

我有:

try:
   (stdin, stdout, stderr) = client.exec_command(s)
except:
   print 'whoops'
   sys.exit()
print stdout.readlines()

但这导致了死锁,出于某种原因,脚本似乎没有任何反应,我最终不得不强制结束整个进程(ctrl+c无效)。我不确定exec_command是否没有正确完成(尽管它已经跳出try/catch块),还是我遇到了网络问题,或者其他什么原因。

有没有什么想法?

更新:

问题出在执行handin命令时的互动上。在执行命令后,handin可能还在运行,也可能已经结束。如果是第一次提交,它会显示成功,等等,然后完成执行,一切正常。但如果我是在重新提交,我需要为每个文件授权覆盖(stdin.write('y'))。

总结:

我该如何检查exec_command()是否仍在运行,是否在等待输入,并相应地从stdout读取?

5 个回答

0

为了绕过这个问题并获取Ifconfig的输出,你可以尝试使用选项 get_pty=True

比如:

import paramiko
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

def MonitorProcess():
    ssh.connect('10.2.0.230', username='ibmsys1', password='passw0rd', timeout=5)
    stdin, stdout, stderr = ssh.exec_command('/sbin/ifconfig', timeout=3, get_pty=True)
    #stdin, stdout, stderr = ssh.exec_command('/sbin/ifconfig') -> simple exec ex.
    print stdout.read()

MonitorProcess()
6

这个问题可能是因为远程命令在等你输入内容(它期待你在标准输入中写点什么,但不知道你不会输入,除非你告诉它)。你可以试试 stdin.channel.shutdown_write()(我觉得单独使用 stdin.close() 是不够的:那样只会让数据刷新一下)。

13

我觉得上面的代码片段没有什么问题。下面这个程序是一个完整的脚本,它可以登录到一个主机上,并运行ls命令来查看文件。我刚试过,运行得很好。你可以试试这个,看它是否对你有效。如果不行,我怀疑可能是你的ssh服务器、你运行的命令,或者paramiko的安装出了问题。如果对你有效,那就只需要对这个进行一些修改,以适应你现有的功能,然后看看哪里出问题。

import paramiko
ssh=paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('<ip address here>',username='<username here>',password='<password here>')
stdin,stdout,stderr = ssh.exec_command("ls /")
print stdout.readlines()

如果这个对你有效,我接下来的建议是试着把'ls /'替换成你想要运行的实际命令。可能那个命令在等待用户输入等情况,所以会卡住。

撰写回答