node.js – 无法创建/ dev / stdout:没有这样的设备或地址

我想通过节点运行
shell命令并捕获stdout的结果.我的脚本在OSX上运行正常,但在Ubuntu上运行不正常.

我已将问题和脚本简化为以下节点脚本:

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.把它与我从herehere得到的结果放在一起,我写了你的代码的这个修改版本:

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上工作.

点赞