我想通过节点运行shell命令并捕获stdout的结果。我的脚本在OSX上运行正常,但在Ubuntu上运行不正常。
我已将问题和脚本简化为以下节点脚本:
var execSync = require('child_process').execSync,
result = execSync('echo "hello world" >> /dev/stdout');
// Do something with result
结果:
/ bin / sh:1:无法创建/ dev / stdout:没有这样的设备或地址
/dev/stdout
/dev/fd/1
execSync('echo ...', {shell : '/bin/bash'})
就像我说的,上面的问题被简化了。真实脚本接受应该写入结果的文件名作为参数,因此我需要通过提供对作为文件描述符的stdout流的访问来解决这个问题,即/dev/stdout
。
如何通过节点执行命令,同时让命令可以访问自己的标准输出流?
答案 0 :(得分:1)
/dev/stdout
我无法访问OSX框,但是phantomjs
上的this issue,似乎在OSX / BSD和Linux /dev/stdout
上都是符号链接,但它仍然是似乎他们之间的工作方式不同。其中一位评论者表示OSX的标准是使用/dev/stdout
而不是Linux。在another random place中我读到了暗示/dev/stdout
几乎是OSX的陈述。可能有一条线索in this answer,说明为什么它在Linux上不起作用(似乎以这种方式隐式关闭文件描述符)。
其他相关问题:
我在Arch上尝试了你的代码,它确实给了我同样的错误,就像上面提到的变化一样 - 所以这与Ubuntu无关。
我找到了一个blog post,它描述了如何将文件描述符传递给execSync
。把它与我从here和here得到的结果放在一起,我写了你的代码的修改版本:
var fs = require('fs');
var path = require('path');
var fdout = fs.openSync(path.join(process.cwd(), 'stdout.txt'), 'a');
var fderr = fs.openSync(path.join(process.cwd(), 'stderr.txt'), 'a');
var execSync = require('child_process').execSync,
result = execSync('echo "hello world"', {stdio: [0,fdout,fderr] });
除非我误解了您的问题,否则您希望能够更改execSync
中命令输出的位置。有了这个,您可以使用文件描述符。如果您希望被调用程序输出到其父级继承的1
和2
,您仍然可以传递stdout
和stderr
,您已在评论中提及
为了便于将来参考,我在4.10.9-1-ARCH
和bash 4.4.12
上使用内核版node v7.7.3
的Arch工作。