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

5
我希望能够通过node运行shell命令并捕获stdout的结果。我的脚本在OSX上运行良好,但在Ubuntu上却不行。
我已经将问题和脚本简化为以下的node脚本:
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
  • 我已经尝试将shell更改为bash... execSync('echo ...', {shell : '/bin/bash'})

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

如何通过node执行命令,同时使命令可以访问其自己的stdout流?


我之前发布了一个类似的问题http://stackoverflow.com/questions/40288461/no-such-device-or-address-dev-stdout,但是我投票关闭了它,因为它太广泛了,而且答案与Python有关。 - Drahcir
那么在Ubuntu上,为什么result = execSync('echo "hello world" ');不会在结果中返回“hello world”呢? - strobelight
@Drahcir 是的,但 /dev/xxxx 不是文件描述符。默认情况下,stdout 的文件描述符为 1,文件的文件描述符为打开文件时返回的文件描述符。也许您需要研究流而不是文件描述符。您的示例希望从运行程序中返回结果。如果该程序将结果写入 stdout,则无需重定向到它。 - strobelight
@strobelight 这将把新程序的标准输出设置为与父进程的标准输出相同,这与将第二个 stdio 元素设置为 "inherit" 相同。这意味着新启动的程序的输出将直接发送到用户的终端。 - Drahcir
这里的简化可能是过于简单了。当shell解析/dev/stdout时(如在>>的情况下),即使操作系统没有提供非shell应用程序可以识别的实际/dev/stdout文件系统实体,它也可以被读取为FD 1。因此,从跨平台行为完全相同的角度来看,>>不是一个可接受的替代品 - 最好使用一个写入命名文件的标准工具,例如tee - Charles Duffy
显示剩余12条评论
1个回答

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] });

除非我误解了您的问题,否则您想要能够更改 execSync 命令的输出位置。使用文件描述符可以实现这一点。如果您想让调用的程序将输出发送到其父进程继承的 stdout 和 stderr,那么仍然可以传递 1 和 2,这一点您已经在评论中提到过。
供参考,此方法在 Arch 上的内核版本为 4.10.9-1-ARCH、bash 版本为 4.4.12 和 Node 版本为 v7.7.3 下可行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接