我想通过其stdin / stdout与(远程)非交互式shell通信,以运行多个命令并读取输出。问题是,如果我在shell stdin上填充多个命令,则无法检测单个命令的输出之间的边界。

在类似Python的伪代码中:

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') 

然后,我可以将 out拆分为零个字符。

其他对我不起作用的方法:
  • 我不想为每个命令运行一个单独的ssh session ,因为握手太重了。
  • 我不想在所创建的 shell 上强制使用ControlMaster选项来尊重最终用户的ssh_config。
  • 我希望不需要用户安装特定的服务器程序。

  • 有没有更好的方法可以在一个 session 中运行多个命令并获得单个输出?有没有采用某种二进制输出模式的广泛部署的shell?

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

    请您参考如下方法:

    对于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 
    


    评论关闭
    IT序号网

    微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!