且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何在 paramiko 中写入标准输入(从 exec_command 返回)?

更新时间:2022-05-13 05:19:20

sys.stdin.read() 将继续阅读直到 EOF 所以在你的 paramiko 脚本中你需要关闭 stdin(从 exec_command() 返回).但是如何?

sys.stdin.read() will keep reading until EOF so in your paramiko script you need to close the stdin (returned from exec_command()). But how?

根据 Paramiko 的文档 (v1.16):

According to Paramiko's doc (v1.16):

警告:要正确模拟从套接字的 makefile() 方法创建的文件对象,需要一个 Channel 及其 ChannelFile 应该能够独立关闭或垃圾收集.目前,关闭 ChannelFile 只会刷新缓冲区.

Warning: To correctly emulate the file object created from a socket’s makefile() method, a Channel and its ChannelFile should be able to be closed or garbage-collected independently. Currently, closing the ChannelFile does nothing but flush the buffer.

2.stdin.channel.close() 也有问题.

由于 stdinstdoutstderr 都共享一个通道,stdin.channel.close()也将关闭 stdoutstderr 这不是预期的.

2. stdin.channel.close() also has problem.

Since stdin, stdout and stderr all share one single channel, stdin.channel.close() will also close stdout and stderr which is not expected.

正确的解决方案是使用 stdin.channel.shutdown_write() 不允许写入通道但仍然允许从通道读取所以 stdout.read()stderr.read() 仍然可以工作.

The correct solution is to use stdin.channel.shutdown_write() which disallows writing to the channel but still allows reading from the channel so stdout.read() and stderr.read() would still work.

看下面的例子,看看stdin.channel.close()stdin.channel.shutdown_write()的区别.

See following example to see the difference between stdin.channel.close() and stdin.channel.shutdown_write().

[STEP 101] # cat foo.py
import paramiko, sys, time

ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy() )
ssh.connect(hostname='127.0.0.1', username='root', password='password')
cmd = "sh -c 'read v; sleep 1; echo $v'"
stdin, stdout, stderr = ssh.exec_command(cmd)
if sys.argv[1] == 'close':
    stdin.write('hello world\n')
    stdin.flush()
    stdin.channel.close()
elif sys.argv[1] == 'shutdown_write':
    stdin.channel.send('hello world\n')
    stdin.channel.shutdown_write()
else:
    raise Exception()
sys.stdout.write(stdout.read() )
[STEP 102] # python foo.py close           # It outputs nothing.
[STEP 103] # python foo.py shutdown_write  # This works fine.
hello world
[STEP 104] #