我试图在远程部署的嵌入式Linux设备上获取python脚本来执行scp命令。执行命令很简单,但如果目标服务器未列在' known_hosts'文件,scp抛出需要与之交互的警告。几天以来我一直反对这一点,我无法解决2个问题。
首先,我无法从子进程中获取非阻塞读取响应以正常运行。在下面的代码中,select总是返回([],[],[]),即使我知道我可以从stderr读取(假设生成了可信主机文件警告)。
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尝试的地方结束,但是等待用户输入?
谢谢!
答案 0 :(得分:1)
问题可能是scp
在这种情况下不使用stdin / stdout / stderr进行通信,而是直接通过终端进行通信。
您可以通过在stackoverflow上搜索scp input
之类的内容来找到许多类似的问题以及解决方法。
启动子进程只会在父级“管道”输出(stdout / stderr)并且子进程尝试写入内容时才会死亡。在这种情况下,scp可能会继续运行,因为它正在使用终端。但是,这些过程并非真正隐藏;您可以使用ps
之类的工具轻松查看它们(并使用kill
或killall
杀死它们。)
import os, pty
pid, fd = pty.fork()
if pid == 0:
os.execvp('scp', ['scp', 'user@remote.com:file', ... ])
else:
while True:
s = os.read(fd, 1024)
print repr(s)
os.write(fd, 'something\n')