【发布时间】:2016-08-12 13:43:50
【问题描述】:
我正在尝试在远程部署的嵌入式 Linux 设备上获取 python 脚本来执行 scp 命令。执行命令很简单,但如果目标服务器未列在 'known_hosts' 文件中,scp 会抛出需要与之交互的警告。几天来一直在努力解决这个问题,但我无法解决两个问题。
首先,我无法以非阻塞方式读取来自子进程的响应以正常运行。在以下代码中,即使我知道可以从 stderr 读取(假设生成了受信任的主机文件警告),select 也始终返回 ( [ ], [ ], [ ] )。
cmdString = 'scp user@remote.com:file localFile -i ~/.ssh/id_rsa'
process = subprocess.Popen(shlex.split(cmdString), shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
while(process.poll() is None):
readable, writable, exceptional = select.select([process.stdout], [], [process.stderr], 1)
if not (readable or writable or exceptional):
# Always hits this condition, although adding an "os.read(...)" here
# will return the error prompt from process.stderr.
print "timeout condition"
else:
# Never makes it here
for e in exceptional:
stderr = os.read(process.stderr.fileno(), 256)
print stderr
for r in readable:
stdout = os.read(process.stdout.fileno(), 256)
print stdout
其次,通过输入 PIPE 提供输入,我无法让子流程超出警告。以下代码从 process.stderr 读取警告代码,但随后挂起,直到我在终端中点击 {enter}。我尝试发送“n”、“n\n”和“\n”,但没有一个会导致子进程继续执行(尽管手动输入时所有 3 种模式都有效)。
cmdString = 'scp user@remote.com:file localFile -i ~/.ssh/id_rsa'
process = subprocess.Popen(shlex.split(cmdString), shell=False, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Correctly grabs warning and displays it
stderr = os.read(process.stderr.fileno(), 256)
print stderr
# Just in case there was some weird race condition or something
time.sleep(0.5)
# Doesn't ever seem to do anything
process.stdin.write('\n')
最后,重要吗?我最初开始调查子进程和 PIPES,因为我使用“os.system(cmdString)”运行 scp,它阻塞了我的线程并迫使我处理这个问题。现在我正在使用子进程,只是触发命令并让它成功或失败是不是很糟糕?失败的子进程最终会消失吗,或者我最终会在运行了数十或数百个隐藏的 scp 尝试但等待用户输入的情况下结束?
谢谢!
【问题讨论】:
标签: python pipe subprocess popen