使用nodejs的生成会导致“未知选项-";和"[[错误:生成ENOENT]")错误 [英] Using nodejs's spawn causes "unknown option -- " and "[Error: spawn ENOENT]" errors

查看:142
本文介绍了使用nodejs的生成会导致“未知选项-";和"[[错误:生成ENOENT]")错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使spawn依次生效rm -rf node_modulesnpm install(在Windows 7上; n x命令由透明安装的CygWin提供.所有 n x命令在命令行上解析就可以了.

I'm trying to get spawn to effect an rm -rf node_modules followed by npm install (on windows 7; nx commands courtesy of a transparently installed CygWin. All nx commands resolve on a commandline just fine).

我最初使用exec进行了此操作,但想在出现stdout/stderr信息时捕获它,因此我认为我会使用spawn,并重写代码以使用它.但是,这破坏了一切.

I initially had this using exec, but wanted to catch the stdout/stderr information as it occurred, so I figured I'd use spawn, and rewrote the code to use that. However, that breaks everything.

重新编写的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); });

但是,运行它会产生以下错误:

However, running this generates the following error:

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

但是,运行它会产生以下错误:

However, running this generates the following error:

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

如何使spawn运行使用exec可以正常运行的相同命令,而又不会在整个地方引发错误?为什么这不起作用?阅读API, http://nodejs.org/api/child_process.html#child_process_child_process_child_process_spawn_command_args_options ,似乎暗示这正是应该使用spawn的方式...

How do I make spawn run the same commands that worked fine using exec without it throwing up errors all over the place? And why does this not work? Reading the API, http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options, seems to suggest this is precisely how one is supposed to use spawn...

推荐答案

在尝试了许多不同的东西之后,我终于看到了Windows上的"npm"实际上是什么,结果是一个叫做npm,以及Windows本机批处理脚本npm.cmd(不知道为什么它是.cmd,应该是.bat,但在那里). Windows的命令解析器将显示npm,请注意它不是可执行文件,请参见npm.cmd,然后注意它是可执行文件,然后将其替代.当您在终端中时,这很有用,但是spawn()不会做任何此类解析:将它传递给npm会使它失败,因为它不是可执行文件.但是,将npm.cmd作为命令传递就可以了.

After lots of trying different things, I finally had a look at what "npm" actually is on windows, and it turns out to be a bash script called npm, as well as a windows-native batch script called npm.cmd (no idea why it's .cmd, that should be .bat, but there you have it). Windows's command resolver will see npm, notice that it's not an executable, see npm.cmd, and then notice that IS an executable, and will then use that instead. This is helpful when you're in a terminal, but spawn() will not do any such resolution: passing it npm will make it fail because it's not an executable. Passing it npm.cmd as command, however, works just fine.

(此外,不确定为什么rm会更早失败,因为它实际上可以正常工作而没有我可以告诉的任何变化.很可能是误读为问题的一部分,而实际上却并非如此.)

(Also, not sure why rm was failing earlier, since that actually works correctly without any changes that I can tell. Probably misread that as part of the problem when in fact it wasn't.)

因此:如果您在Windows中遇到spawn并说ENOENT,则当您尝试触发的命令在普通命令提示符下工作时,请确定您正在调用的命令是否为真正的可执行文件,或者是否存在.bat/.cmd文件,命令提示符将为您"运行.如果是这样,请生成它.

So: if you run into spawn saying ENOENT in windows, when the command you're trying to trigger works in a plain command prompt, find out if the command you're calling is a true executable, or whether there's a .bat/.cmd file that the command prompt will "helpfully" run for you instead. If so, spawn that.

修改

由于此帖子仍在投票中,因此确保该命令始终有效的一个好方法是根据process.platform对其进行引导,对于Windows,它将为win32.

since this post is still getting upvotes, a good way to ensure the command always works is to bootstrap it based on process.platform, which will be win32 for windows.

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

针对触发此错误的用例的修改

edit specific to the use-case that triggered this error

自发布此问题(及其答案)以来,已经发布了一些软件包,这些软件包允许运行npm任务而不必依赖exec或spawn,您应该改而使用它们.

since posting this question (and its answer), several packages have been released that allow running npm tasks without having to rely on exec or spawn, and you should use them instead.

可能最受欢迎的是 npm-run-all ,它不会它不仅使您能够从其他npm脚本以及从节点运行任何npm任务,而且还添加了用于以串行或并行方式运行多个npm脚本(带有或不带有通配符)的命令.

Probably the most popular is npm-run-all which doesn't just give you the power to run any npm task from other npm scripts as well as from Node, but also adds commands to run multiple npm scripts in series or in parallel, with or without wildcards.

在原始问题的上下文中,由于我试图以exec/spawn的身份运行npm以便进行清理和重新安装而引发了错误,现代的解决方案是在其中执行专门的清理任务package.json:

In the context of the original question, where the error got thrown because I was trying to run npm as an exec/spawn in order to effect a cleanup and reinstall, the modern solution is to have a dedicated cleaning task in package.json:

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

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

And to then invoke that clean task followed by the install command on the command line as

> npm run clean && npm install

或者,在某些Node脚本中,使用:

Or, from inside some Node script, using:

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

这篇关于使用nodejs的生成会导致“未知选项-";和"[[错误:生成ENOENT]")错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆