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

Dra*_*cir 5 linux bash sh node.js

我想通过节点运行 shell 命令并捕获标准输出的结果。我的脚本在 OSX 上运行良好,但在 Ubuntu 上运行不正常。

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

var execSync = require('child_process').execSync,
    result = execSync('echo "hello world" >> /dev/stdout');

// Do something with result
Run Code Online (Sandbox Code Playgroud)

结果是:

/bin/sh: 1: 无法创建 /dev/stdout: 没有这样的设备或地址

  • 我曾尝试更换/dev/stdout/dev/fd/1
  • 我曾尝试将外壳更改为 bash ... execSync('echo ...', {shell : '/bin/bash'})

就像我说的,上面的问题被简化了。真正的脚本接受应该写入结果的文件的名称作为参数,因此我需要通过提供对 stdout 流作为文件描述符的访问来解决这个问题,即/dev/stdout.

如何通过节点执行命令,同时让命令访问其自己的标准输出流?

mec*_*ynx 2

/dev/stdout

我无法访问 OSX 盒子,但从这个问题开始phantomjs,似乎虽然在 OSX/BSD 和 Linux 上/dev/stdout都是符号链接,但它们之间的工作方式似乎有所不同。一位评论者表示,这是 OSX 上使用的标准/dev/stdout,但不适用于 Linux。在另一个随机的地方,我读到了暗示这/dev/stdout几乎是 OSX 的事情的陈述。这个答案可能有一个线索,说明为什么它在 Linux 上不起作用(以这种方式使用时似乎会隐式关闭文件描述符)。

更多相关问题:

解决方案

我在 Arch 上尝试了你的代码,它确实给了我同样的错误,就像提到的变体一样 - 所以这与 Ubuntu 无关。

我发现一篇博客文章描述了如何将文件描述符传递给execSync. 将其与我从此处此处获得的内容结合起来,我编写了代码的修改版本:

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] });
Run Code Online (Sandbox Code Playgroud)

除非我误解了你的问题,否则你希望能够更改命令输出的位置execSync。有了这个,您可以使用文件描述符。如果您希望被调用的程序输出到其父程序并由其继承,您仍然可以传递1and ,您已经在注释中提到了这一点。2stdoutstderr

为了供将来参考,这适用于内核版本为4.10.9-1-ARCHbash 4.4.12和的 Arch node v7.7.3