使用 nodejs 的生成会导致"unknown option -- "和"[Error: spawn ENOENT]"错误



我正试图让spawn实现rm -rf node_modules,然后是npm install(在windows 7上;nx命令由透明安装的CygWin提供。所有nx命令都可以在命令行上解析)。

我最初使用exec,但希望在发生stdout/stderr信息时捕获它,所以我想使用spawn,并重写代码以使用它。然而,这打破了一切。

重写后的rm命令变为:

var spawn = require("child_process").spawn,
    child = spawn("rm", ["-rf", "node_modules"]);
child.stdout.on('data', function (data) { console.log(data.toString()); });
child.stderr.on('data', function (data) { console.log(data.toString()); });
child.on('error', function() { console.log(arguments); });

但是,运行此操作会产生以下错误:

rm: unknown option -- ,
Try `rm --help' for more information.

经过重写的npm命令变成了这样:

var spawn = require("child_process").spawn,
    child = spawn("npm", ["install"]);
child.stdout.on('data', function (data) { console.log(data.toString()); });
child.stderr.on('data', function (data) { console.log(data.toString()); });
child.on('error', function() { console.log(arguments); });

但是,运行此操作会产生以下错误:

{
  '0': {
    [Error: spawn ENOENT]
    code: 'ENOENT',
    errno: 'ENOENT',
    syscall: 'spawn'
  }
}

如何使spawn运行与使用exec运行良好的命令相同的命令,而不会到处出现错误?为什么这不起作用?阅读API,http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options,似乎表明这正是一个人应该如何使用产卵。。。

在尝试了很多不同的东西之后,我终于看到了什么"npm";实际上是在windows上,它是一个名为npm的bash脚本,以及一个称为npm.cmd的windows本机批处理脚本(不知道为什么是.cmd,应该是.bat,但现在已经有了)。Windows的命令解析程序将看到npm,注意到它不是可执行文件,请看到npm.cmd,然后注意到IS是可执行文件。当您在终端中时,这很有帮助,但spawn()不会执行任何这样的解析:传递它npm会使它失败,因为它不是可执行文件。然而,将它作为命令传递给npm.cmd,效果很好。

(此外,我也不确定rm为什么早些时候失败了,因为这实际上是正确的,没有任何变化。可能误解了这是问题的一部分,而事实并非如此。)

所以:如果你在windows中遇到spawn说ENOENT,当你试图触发的命令在普通命令提示符下工作时,要弄清楚你调用的命令是否是一个真正的可执行文件,或者是否有一个.bat/.cmd文件,命令提示符会";有益的";替你跑。如果是这样的话,那就繁殖它。

编辑

由于这篇文章仍在获得支持,确保该命令始终有效的一个好方法是基于process.platform引导它,这将是windows的win32

var npm = (process.platform === "win32" ? "npm.cmd" : "npm"),
    child = spawn(npm, ["install", ...]);
...

特定于触发此错误的用例的编辑

自从发布这个问题(及其答案)以来,已经发布了几个包,允许运行npm任务,而不必依赖exec或spawn,您应该使用它们。

可能最流行的是npm-run-all,它不仅可以让您从其他npm脚本以及Node运行任何npm任务,还可以添加命令,以串行或并行运行多个npm脚本,无论是否使用通配符。

在最初的问题中,由于我试图以exec/spown的身份运行npm以进行清理和重新安装,因此引发了错误,现代的解决方案是在package.json:中有一个专用的清理任务

{
  ...
  "scripts": {
    "clean": "rimraf ./node_modules",
    ...
  },
  ...
}

然后调用clean任务,然后在命令行上调用作为的安装命令

> npm run clean && npm install

或者,从某个Node脚本内部,使用:

const runAll = require("npm-run-all");
...
runAll(["clean", "install"])
    .then(() => {
        console.log("done!");
    })
    .catch(err => {
        console.log("failed!");
    });

(当然,也可以作为package.js中的复合脚本,例如"redo": "run-s clean install",然后使用runAll(["redo"])

我认为这可能是某种cygwin gotcha。我正在运行Ubuntu 12.04,并试图复制你的问题,但它对我来说很好。总之,我看不出你做错了什么。

如果它抱怨这个选项,也许可以把它分成多个选项,比如:

child = spawn("rm", ["-r", "-f", "node_modules"]);

这有点像冰雹玛丽,但它也适用于我的Ubuntu 12.04。你可以试着只删除一个文件,看看你是否得到了同样的东西。

child = spawn("rm", ["/home/username/Desktop/TestFile"]);

如果这仍然失败,那么你就知道你在与一些疯狂的东西作斗争。

你甚至可以尝试只执行一个没有参数的命令,比如:

child = spawn("ls");

如果这仍然失败了,我想你们根本不可能让spawn工作,并感谢至少exec在工作。

对你来说,答案不多,但正如我所说,我看不出你做错了什么。

此外,我看不出你的npm命令将如何工作,因为你没有指定要安装什么,但也就是说,如果我使用相同的命令,它会以不同的方式失败。我看到了很多stderr输出,而不是一个整体错误。

顺便说一句,我正在运行节点v0.8.21。您可以通过node-v查询。如果您正在运行另一个版本,请尝试0.8.21。

对流程使用完整路径,如:

var cmd = require('child_process').spawn("C:\windows\system32\cmd.exe");

相关内容

  • 没有找到相关文章

最新更新