我已将问题和脚本简化为以下节点脚本:
var execSync = require('child_process').execSync, result = execSync('echo "hello world" >> /dev/stdout'); // Do something with result
结果是:
/bin/sh: 1: cannot create /dev/stdout: No such device or address
>我尝试用/ dev / fd / 1替换/ dev / stdout
>我尝试将shell更改为bash … execSync(‘echo …’,{shell:’/ bin / bash’})
就像我说的,上面的问题被简化了.真实脚本接受应该写入结果的文件名作为参数,因此我需要通过提供对作为文件描述符的stdout流的访问来解决这个问题,即/ dev / stdout.
如何通过节点执行命令,同时让命令访问自己的stdout流?
在/ 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上不起作用(似乎以这种方式隐式关闭文件描述符).
其他相关问题:
> https://unix.stackexchange.com/questions/36403/portability-of-dev-stdout
> bash redirect to /dev/stdout: Not a directory
解决方案
我在Arch上尝试了你的代码,它确实给了我同样的错误,就像上面提到的变化一样 – 所以这与Ubuntu无关.
我找到了一个描述如何将文件描述符传递给execSync的blog post.把它与我从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中命令输出的位置.有了这个,您可以使用文件描述符.如果您希望被调用的程序输出到其父级继承的stdout和stderr,您仍然可以传递1和2,您已在评论中提到过.
为了将来参考,这在Arch上使用内核版本4.10.9-1-ARCH,在bash 4.4.12和节点v7.7.3上工作.