我想通过stdin / stdout与(远程)非交互式shell进行通信,以运行多个命令并读取输出。问题是如果我在shell stdin上填充多个命令,我就无法检测到各个命令的输出之间的界限。
类似Python的伪代码:
Observable
但显然sh = Popen(['ssh', 'user@remote', '/bin/bash'], stdin=PIPE, stdout=PIPE)
sh.stdin.write('ls /\n')
sh.stdin.write('ls /usr\n')
sh.stdin.close()
out = sh.stdout.read()
包含两个连接命令的输出,我无法可靠地拆分它们。
到目前为止,我最好的想法是在输出之间插入out
个字节:
\0
然后我可以将sh.stdin.write('ls /; echo -ne "\0"\n')
sh.stdin.write('ls /usr; echo -ne "\0"\n')
分成零个字符。
其他不适合我的方法:
有没有更好的方法在一个会话中运行多个命令并获得单独的输出?是否有广泛部署的shell具有某种二进制输出模式?
PS。有一个重复的问题,但它没有一个令人满意的答案: Run multiple commands in a single ssh session using popen and save the output in separate files
答案 0 :(得分:1)
对于SSH,我使用了paramiko及其invoke_shell方法来创建一个可编程管理的shell实例。
以下不是一个完整的答案,它仍然是hacky,但我觉得这是朝着正确方向迈出的一步。
我在Windows中需要相同的读/写shell实例功能,但没有运气,所以我稍微扩展了你的方法(顺便说一句,谢谢你的想法)。
我通过在每个命令之间放置一个条件退出来验证每个命令是否基于其退出代码成功执行,然后我使用所述条件检查的文本(已知字符串)作为定界符来定义每个命令的响应。
一个粗略的例子:
from subprocess import Popen, PIPE
sh = Popen('cmd', stdin=PIPE, stdout=PIPE)
sh.stdin.write(b'F:\r\n')
sh.stdin.write(b"if not %errorlevel% == 0 exit\r\n")
sh.stdin.write(b'cd F:\\NewFolder\r\n')
sh.stdin.write(b"if not %errorlevel% == 0 exit\r\n")
sh.stdin.write('...some useful command with the current directory confirmed as set to F:\NewFolder...')
sh.stdin.close()
out = sh.stdout.read()
sh.stdout.close()
# Split 'out' by each line that ends with 'if not %errorlevel% == 0 exit' and do what you require with the responses