我正在使用python的paramiko模块连接到远程机器,并使用大量文件(超过14K文件和60 + gig数据)使用tar / ZIP文件夹。得到的拉链本身约10演出。现在我可以直接从机器上运行zip / tar命令,没有任何问题。但是,当我尝试通过SSHClient的exec_command运行相同的命令时,它运行了一段时间,但最终远程机器上的压缩过程进入休眠状态。而recv_exit_status只是无限期挂起。这是我正在使用的代码:
stdin, stdout, stderr = ssh.exec_command('cd myDirectory; tar -zcvf output.tgz *')
status = stdout.channel.recv_exit_status()
我也尝试过使用Zip。
stdin, stdout, stderr = ssh.exec_command('cd myDirectory; find -name "*.gz" | zip output.zip -@')
status = stdout.channel.recv_exit_status()
在这两种情况下,如果我直接从远程计算机运行命令,它将完成压缩/ TARing。结果文件就像9演出。但是当我从paramiko尝试它时,它开始,超过一半(6's演出),然后过程进入睡眠状态!
我使用top监视远程计算机上的进程,zip / tar将开始运行,但最终会在完成之前进入休眠状态。并且python脚本将无限期挂起。
为什么会发生这种情况?
答案 0 :(得分:1)
可能与超时有关。尝试将timeout
param(以秒为单位)添加到呼叫中:exec_command(timeout=20*60)
。这是20分钟的例子。
有关详细信息,请参阅该方法的文档字符串:
def exec_command(self, command, bufsize=-1, timeout=None, get_pty=False):
"""
Execute a command on the SSH server. A new `.Channel` is opened and
the requested command is executed. The command's input and output
streams are returned as Python ``file``-like objects representing
stdin, stdout, and stderr.
:param str command: the command to execute
:param int bufsize:
interpreted the same way as by the built-in ``file()`` function in
Python
:param int timeout:
set command's channel timeout. See `Channel.settimeout`.settimeout
:return:
the stdin, stdout, and stderr of the executing command, as a
3-tuple
:raises SSHException: if the server fails to execute the command
"""
还有另一个我遇到的问题,也可能有所贡献:https://github.com/paramiko/paramiko/issues/109
在https://github.com/paramiko/paramiko/issues/109#issuecomment-111621658
中尝试我的建议我也遇到过这个问题,这是由于stdout.channel.eof_received == 0
import paramiko
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect("1.1.1.1", username="root", password="pass")
stdin, stdout, stderr = client.exec_command("service XXX start")
stdin,stdout和stderr保持开放......
>>> print stdin
<paramiko.ChannelFile from <paramiko.Channel 3 (open) window=2097152 in-buffer=50 -> <paramiko.Transport at 0x17eff90L (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>
>>> print stdout
<paramiko.ChannelFile from <paramiko.Channel 3 (open) window=2097152 in-buffer=50 -> <paramiko.Transport at 0x17eff90L (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>
>>> print stderr
<paramiko.ChannelFile from <paramiko.Channel 3 (open) window=2097152 in-buffer=50 -> <paramiko.Transport at 0x17eff90L (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>>
因此未收到EOF ......
>>> print stdin.channel.eof_received
0
通常我收到True并且可以只是stdout.read(),但为了安全起见我使用此解决方法(有效!):等待超时,强制stdout.channel.close()然后stdout.read() :
>>> timeout = 30
>>> import time
>>> endtime = time.time() + timeout
>>> while not stdout.channel.eof_received:
... sleep(1)
... if time.time() > endtime:
... stdout.channel.close()
... break
>>> stdout.read()
'Starting XXX: \n[ OK ]\rProgram started . . .\n'
>>>
答案 1 :(得分:0)
我刚刚遇到类似的事情。我可以在通过ssh登录时运行命令,但是通过S
运行最终会使命令进入休眠状态(htop
中的stderr
)。我发现可能是由于命令在stdout
或> /dev/null 2>&1
上产生了太多输出,我收集的信息可以溢出缓冲区,导致命令已完成的信号迷路了,但我绝对不是专家。我找到的是在命令的末尾添加stdout
(从而消除了paramiko触摸stderr
和exec_command
的需要)允许相同的命令通过{{1}完成}。
总之,我的工作流程如下所示:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('999.99.99.99', username='me', key_filename='my_key')
stdin, stdout, stderr = ssh.exec_command('my_command > /dev/null 2>&1')
stdout_content = stdout.read()
stderr_content = stderr.read()
ssh.close()
现在可以使用,但如果有人知道如何解决原始问题而不得不更改命令以重定向stdout
和stderr
,我仍然会非常感兴趣
答案 2 :(得分:0)
我的解决方法是client.exec_command('my_cmd', get_pty=True)
。
get_pty=True
可以从服务器请求伪终端。
因此,如果您可以在ssh会话中运行命令,那么也应该使用exec_command()
函数。