2016-03-07 71 views
1

我想通过其标准输入/输出(远程)非交互壳运行多个命令和读取的输出进行通信。问题是,如果我在shell stdin中填充多个命令,我无法检测到各个命令的输出之间的界限。运行在非交互式shell会话多个命令和解析输出

在Python般的伪代码:

sh = Popen(['ssh', '[email protected]', '/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') 

然后我可以在零个字符分割out

  • 我不想每运行命令单独SSH会话,因为握手是太重量级:

    不为我工作的其他方法。

  • 我宁愿不给力,在创建壳ControlMaster选择尊重最终用户的ssh_config中。
  • 我宁愿没有必要要求用户安装特定的服务器程序。

是否有更好的方式在一个会话中运行几个命令并获取单独的输出?是否有一种广泛部署的shell具有某种二进制输出模式?

PS。有一个重复的问题,但它没有一个满意的答案: Run multiple commands in a single ssh session using popen and save the output in separate files

+1

如果你可以运行像Python在远程系统上的脚本,你总是可以通过命令,并在咸菜或JSON的输出编码。尽管你可以保证输出不会包含空字符,但你的方法对我来说似乎还可以。它与多部分MIME编码类似,除了使用通常包含长随机字符的边界字符串以最小化冲突的可能性。 –

+1

你可以改变你的过程到一个循环?对于每个命令,编写命令,刷新缓冲区,然后读取结果? –

+1

先生美洲驼,没有办法检测到发出的命令已经完成运行(而不是仅仅产生下一块输出)。 –

回答

1

对于SSH我用paramiko及其invoke_shell方法来创建一个程序,管理shell实例。

以下不是一个完整的答案,它仍然是哈克,但我觉得这是朝着正确方向迈出的一步。

我需要在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