【问题标题】:Read output from subprocess without using pipes从子进程读取输出而不使用管道
【发布时间】:2017-01-12 12:23:56
【问题描述】:

我正在尝试运行 bash.exe(适用于 Windows 的 Ubuntu 上的 Bash)作为 Sublime Text 的构建命令。但是,bash.exe 有一个 bug,不支持将其 stdout 输出到任何管道。

问题是这样的:如何运行 cmd 行(即“bash.exe -c ls”)并捕获输出,而无需将 bash.exe 输出到 Windows 上的管道中?

我愿意在 Windows 上使用任何语言或环境来制作此工具。

编辑

我跑了 bashTest = subprocess.Popen(["bash.exe", "-c", "ls"]), stdout=subproccess.PIPE)

结果:

bashTest.communicate()[0] b'E\x00r\x00r\x00o\x00r\x00:\x00\x000\x00x\x008\x000\x000\x007\x000\x000\x005\x007\x00\r\x00\r\x00\n\x00'

【问题讨论】:

  • 你可以使用这样的管道:echo "hello world" | { read test; echo test=$test; },甚至可以编写这样的函数:read_from_pipe() { read "$@" <&0; }
  • 问题是任何时候代码都试图将 bash.exe 的输出打印到管道,正如github page 所说,提供的唯一信息是一些随机错误消息。管道根本不能成为流程的一部分。
  • 请发布错误和您的输入
  • [为清楚起见,评论移至主要问题编辑]

标签: windows bash pipe subprocess windows-subsystem-for-linux


【解决方案1】:

目前这是不可能的。有一个 github issue about it 已作为已知限制关闭。如果您想提高对它的认识,我看到了 2 个相关的 User Voice 想法:Allow Windows programs to spawn BashAllow native Win32 applications to launch Linux tools/commands

但是,您可以通过多种方式绕过它。一种方法是编写一个在 bash.exe 控制台中永远循环的脚本。当脚本收到信号时,它会运行 Linux 命令并将输出通过管道传输到文件,然后发出信号表明它已完成。这是一些伪代码:

Linux:

while true
  while not exists /mnt/c/dobuild
    sleep 1
  end
  gcc foo.c > /mnt/c/build.log
  rm /mnt/c/dobuild
end

窗户:

touch C:\dobuild
while exists C:\dobuild
  sleep 1
end
cat C:\build.log

这确实需要在脚本运行时始终打开 bash.exe 控制台,这并不理想。

已经提到的另一个潜在解决方法是使用ReadConsoleOutput

【讨论】:

    【解决方案2】:

    您需要使用选项shell=True in Popen() 才能使管道正常工作。

    像这个例子不需要拆分这个命令。

    >>> import subprocess as sp    
    >>> cmd = 'echo "test" | cat'
    >>> process = sp.Popen(cmd,stdout=sp.PIPE,shell=True)
    >>> output = process.communicate()[0]
    >>> print output
    test
    

    【讨论】:

    • 不幸的是,没有改变任何东西。如果您怀疑我遇到的问题,我提到的github page 非常清楚不兼容问题。我正在寻找一些使用管道的解决方法。
    • 您还可以使用进程替换重定向到子shell:command > >(stdlog pipe) 2> >(stderr pipe) 例如命令2> >(grep 'something') >/dev/null
    • @khakishoiab:请注意,问题不是关于 Linux、Cygwin 等上通常的 bash,而是关于 WSL。在 WSL 的 Windows 端,“bash”不是真正的 bash shell,它是一个启动器,它使某些 hocus-pocus 导致真正的 bash 在“linux”环境中启动,它的标准输入和标准输出通过管道传输到 Windows 控制台框.很复杂,
    【解决方案3】:

    如果您等不及修复,您唯一现实的选择是使用ReadConsoleOutput 和/或相关功能。

    【讨论】:

      猜你喜欢
      • 2014-01-20
      • 2018-06-03
      • 2016-02-06
      • 2021-10-13
      • 2014-02-10
      • 2015-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多