请告诉我为什么会出现这种死锁:从 Paramiko exec_command() file-like objects 读取和写入 -- ChannelFile.close() 不起作用
Please tell me why this deadlocks: Reading and writing from Paramiko exec_command() file-like objects -- ChannelFile.close() does not work
import paramiko, threading
def Reader(src):
while True:
data = src.readline()
if not data: break
print data
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect("172.17.0.2", username="test", password="test")
stdin, stdout, stderr = client.exec_command("dd of=readme.txt")
reader = threading.Thread(target=Reader, args=(stderr, ))
reader.start()
stdin.write("some data")
stdin.flush()
stdin.close()
reader.join()
此代码在 join() 处永远等待。如果我删除 stderr 写入线程,它会按预期工作,将正确的文本写入文件 'readme.txt',但我会丢失 dd stderr 消息。
问题出在stdin.close()
。根据 Paramiko 的文档 (v1.16):
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.
所以你必须使用stdin.channel.close()
.
更新:
由于 stdin、stdout 和 stderr 都共享一个通道,stdin.channel.close()
也会关闭 stderr 所以你的 Reader
线程可能什么也得不到。解决方案是使用 stdin.channel.shutdown_write()
,它不允许写入通道但仍然允许从通道读取。
验证它工作正常:
[STEP 101] # cat foo.py
import paramiko, threading, paramiko
def Reader(src):
while True:
data = src.read()
if not data: break
print data,
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect("10.11.12.13", username="root", password="password")
stdin, stdout, stderr = client.exec_command("dd of=/tmp/file")
reader = threading.Thread(target=Reader, args=(stderr,) )
reader.start()
stdin.write("some data")
stdin.flush()
stdin.channel.shutdown_write()
reader.join()
[STEP 102] # python foo.py
0+1 records in
0+1 records out
[STEP 103] #
import paramiko, threading
def Reader(src):
while True:
data = src.readline()
if not data: break
print data
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect("172.17.0.2", username="test", password="test")
stdin, stdout, stderr = client.exec_command("dd of=readme.txt")
reader = threading.Thread(target=Reader, args=(stderr, ))
reader.start()
stdin.write("some data")
stdin.flush()
stdin.close()
reader.join()
此代码在 join() 处永远等待。如果我删除 stderr 写入线程,它会按预期工作,将正确的文本写入文件 'readme.txt',但我会丢失 dd stderr 消息。
问题出在stdin.close()
。根据 Paramiko 的文档 (v1.16):
Warning: To correctly emulate the file object created from a socket’s
makefile()
method, aChannel
and itsChannelFile
should be able to be closed or garbage-collected independently. Currently, closing theChannelFile
does nothing but flush the buffer.
所以你必须使用.stdin.channel.close()
更新:
由于 stdin、stdout 和 stderr 都共享一个通道,stdin.channel.close()
也会关闭 stderr 所以你的 Reader
线程可能什么也得不到。解决方案是使用 stdin.channel.shutdown_write()
,它不允许写入通道但仍然允许从通道读取。
验证它工作正常:
[STEP 101] # cat foo.py
import paramiko, threading, paramiko
def Reader(src):
while True:
data = src.read()
if not data: break
print data,
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect("10.11.12.13", username="root", password="password")
stdin, stdout, stderr = client.exec_command("dd of=/tmp/file")
reader = threading.Thread(target=Reader, args=(stderr,) )
reader.start()
stdin.write("some data")
stdin.flush()
stdin.channel.shutdown_write()
reader.join()
[STEP 102] # python foo.py
0+1 records in
0+1 records out
[STEP 103] #