如何在node.js上调试“错误:生成ENOENT”?

本文翻译自:How do I debug “Error: spawn ENOENT” on node.js?

When I get the following error: 当我得到以下错误:

events.js:72
        throw er; // Unhandled 'error' event
              ^
Error: spawn ENOENT
    at errnoException (child_process.js:1000:11)
    at Process.ChildProcess._handle.onexit (child_process.js:791:34)

What procedure can I follow to fix it? 我可以按照什么程序来修复它?

Author note : Lots of issues with this error encouraged me to post this question for future references. 作者注意 :许多与此错误有关的问题鼓励我发布此问题以供将来参考。

Related questions: 相关问题:

  • using spawn function with NODE_ENV=production 将生成功能与NODE_ENV = production一起使用
  • node.js child_process.spawn ENOENT error - only under supervisord node.js child_process.spawn ENOENT错误-仅在监督下
  • spawn ENOENT node.js error 产生ENOENT node.js错误
  • https://stackoverflow.com/questions/27603713/nodejs-spawn-enoent-error-on-travis-calling-global-npm-package https://stackoverflow.com/questions/27603713/nodejs-spawn-enoent-error-on-travis-calling-global-npm-package
  • Node JS - child_process spawn('npm install') in Grunt task results in ENOENT error 节点JS-Grunt任务中的child_process spawn('npm install')导致ENOENT错误
  • Running "foreman" task Fatal error: spawn ENOENT 运行“ foreman”任务致命错误:生成ENOENT
  • unhandled error event in node js Error: spawn ENOENT at errnoException (child_process.js:975:11) 节点js中未处理的错误事件错误:在errnoException处生成ENOENT(child_process.js:975:11)
  • Node.js SpookyJS: error executing hello.js Node.js SpookyJS:执行hello.js时出错
  • https://stackoverflow.com/questions/26572214/run-grunt-on-a-directory-nodewebkit https://stackoverflow.com/questions/26572214/run-grunt-on-a-directory-nodewebkit
  • Run exe file with Child Process NodeJS 使用子进程NodeJS运行exe文件
  • Node: child_process.spawn not working on Java even though it's in the path (ENOENT) 节点:child_process.spawn即使在路径中也无法在Java上运行(ENOENT)
  • spawn ENOENT error with NodeJS (PYTHON related) 使用NodeJS生成ENOENT错误 (与PYTHON相关)
  • image resizing is not working in node.js (partial.js) (non-installed dependency) 图像调整大小在node.js(partial.js)中不起作用 (未安装的依赖项)
  • npm install error ENOENT (build dependency problem) npm安装错误ENOENT (构建依赖项问题)
  • Cannot install node.js - oracle module on Windows 7 (build dependency problem) 无法在Windows 7上安装node.js-oracle模块 (生成依赖项问题)
  • Error installing gulp using nodejs on windows (strange case) 在Windows上使用Node.js安装Gulp时发生错误 (奇怪的情况)

#1楼

参考:https://stackoom.com/question/1sB7c/如何在node-js上调试-错误-生成ENOENT


#2楼

Step 1: Ensure spawn is called the right way 步骤1:确保以正确的方式调用spawn

First, review the docs for child_process.spawn( command, args, options ) : 首先,查看child_process.spawn(command,args,options)的文档 :

Launches a new process with the given command , with command line arguments in args . 使用给定command启动新进程,并在args使用命令行参数。 If omitted, args defaults to an empty Array. 如果省略,则args默认为空数组。

The third argument is used to specify additional options, which defaults to: 第三个参数用于指定其他选项,默认为:

{ cwd: undefined, env: process.env }

Use env to specify environment variables that will be visible to the new process, the default is process.env . 使用env指定对新进程可见的环境变量,默认值为process.env

Ensure you are not putting any command line arguments in command and the whole spawn call is valid . 确保您不会把任何命令行参数的command ,整个spawn呼叫是有效的 Proceed to next step. 继续进行下一步。

Step 2: Identify the Event Emitter that emits the error event 步骤2:确定发出错误事件的事件发射器

Search on your source code for each call to spawn , or child_process.spawn , ie 在源代码中搜索对spawnchild_process.spawn每次调用,即

spawn('some-command', [ '--help' ]);

and attach there an event listener for the 'error' event, so you get noticed the exact Event Emitter that is throwing it as 'Unhandled'. 并在其中附加一个针对“错误”事件的事件侦听器,因此您会注意到将其视为“未处理”的确切事件发射器。 After debugging, that handler can be removed. 调试后,可以删除该处理程序。

spawn('some-command', [ '--help' ])
  .on('error', function( err ){ throw err })
;

Execute and you should get the file path and line number where your 'error' listener was registered. 执行,您应该获得注册“错误”侦听器的文件路径和行号。 Something like: 就像是:

/file/that/registers/the/error/listener.js:29
      throw err;
            ^
Error: spawn ENOENT
    at errnoException (child_process.js:1000:11)
    at Process.ChildProcess._handle.onexit (child_process.js:791:34)

If the first two lines are still 如果前两行仍然

events.js:72
        throw er; // Unhandled 'error' event

do this step again until they are not. 再次执行此步骤,直到没有。 You must identify the listener that emits the error before going on next step. 在继续下一步之前,您必须确定发出错误的侦听器。

Step 3: Ensure the environment variable $PATH is set 步骤3:确保设置了环境变量$PATH

There are two possible scenarios: 有两种可能的方案:

  1. You rely on the default spawn behaviour, so child process environment will be the same as process.env . 您依赖于默认的spawn行为,因此子进程环境将与process.env相同。
  2. You are explicity passing an env object to spawn on the options argument. 您明确地传递了一个env对象以在options参数上spawn

In both scenarios, you must inspect the PATH key on the environment object that the spawned child process will use. 在这两种情况下,您都必须检查生成的子进程将使用的环境对象上的PATH键。

Example for scenario 1 方案1的示例

// inspect the PATH key on process.env
console.log( process.env.PATH );
spawn('some-command', ['--help']);

Example for scenario 2 方案2的示例

var env = getEnvKeyValuePairsSomeHow();
// inspect the PATH key on the env object
console.log( env.PATH );
spawn('some-command', ['--help'], { env: env });

The absence of PATH (ie, it's undefined ) will cause spawn to emit the ENOENT error , as it will not be possible to locate any command unless it's an absolute path to the executable file. 缺少PATH (即undefined )将导致spawn发出ENOENT错误 ,因为除非它是可执行文件的绝对路径,否则将无法定位任何command

When PATH is correctly set, proceed to next step. 正确设置PATH ,请继续下一步。 It should be a directory, or a list of directories. 它应该是目录或目录列表。 Last case is the usual. 最后一种情况是通常的。

Step 4: Ensure command exists on a directory of those defined in PATH 步骤4:确保command存在于PATH定义的目录中

Spawn may emit the ENOENT error if the filename command (ie, 'some-command') does not exist in at least one of the directories defined on PATH . 如果在PATH定义的至少一个目录中不存在文件名command (即“ some-command”),则Spawn可能会发出ENOENT错误。

Locate the exact place of command . 找到确切的command On most linux distributions, this can be done from a terminal with the which command. 在大多数Linux发行版中,这可以从终端使用which命令来完成。 It will tell you the absolute path to the executable file (like above), or tell if it's not found. 它会告诉您可执行文件的绝对路径(如上),或者告诉您是否找不到该文件。

Example usage of which and its output when a command is found 找到命令时的用法及其输出的示例用法

> which some-command
some-command is /usr/bin/some-command

Example usage of which and its output when a command is not found 找不到命令时的用法及其输出的示例用法

> which some-command
bash: type: some-command: not found

miss-installed programs are the most common cause for a not found command. 缺少安装的程序是找不到命令的最常见原因。 Refer to each command documentation if needed and install it. 如果需要,请参考每个命令文档并进行安装。

When command is a simple script file ensure it's accessible from a directory on the PATH . 当command是一个简单的脚本文件时,请确保可以从PATH上的目录访问它。 If it's not, either move it to one or make a link to it. 如果不是,请将其移至一个或建立链接。

Once you determine PATH is correctly set and command is accessible from it, you should be able to spawn your child process without spawn ENOENT being thrown. 一旦确定正确设置了PATH并可以从中访问command ,您就应该能够生成子进程而不会抛出spawn ENOENT


#3楼

NOTE: This error is almost always caused because the command does not exist, because the working directory does not exist, or from a windows-only bug. 注意:此错误几乎总是由命令不存在,工作目录不存在或仅Windows引起的。

I found a particular easy way to get the idea of the root cause of: 我找到了一种特别简单的方法来了解以下根本原因:

Error: spawn ENOENT

The problem of this error is, there is really little information in the error message to tell you where the call site is, ie which executable/command is not found, especially when you have a large code base where there are a lot of spawn calls. 此错误的问题是,错误消息中实际上没有什么信息可以告诉您调用站点在哪里,即找不到哪个可执行文件/命令,尤其是当您的代码库很大且有很多派生调用时。 On the other hand, if we know the exact command that cause the error then we can follow @laconbass' answer to fix the problem. 另一方面,如果我们知道导致错误的确切命令,则可以按照@laconbass的回答来解决问题。

I found a very easy way to spot which command cause the problem rather than adding event listeners everywhere in your code as suggested in @laconbass' answer. 我发现了一种非常简单的方法来找出导致该问题的命令,而不是像@laconbass的答案中所建议的那样在代码中的各处添加事件监听器。 The key idea is to wrap the original spawn call with a wrapper which prints the arguments send to the spawn call. 关键思想是使用包装器包装原始的spawn调用,该包装器将打印发送到spawn调用的参数。

Here is the wrapper function, put it at the top of the index.js or whatever your server's starting script. 这是包装器函数,将其放在index.js或任何服务器启动脚本的顶部。

(function() {
    var childProcess = require("child_process");
    var oldSpawn = childProcess.spawn;
    function mySpawn() {
        console.log('spawn called');
        console.log(arguments);
        var result = oldSpawn.apply(this, arguments);
        return result;
    }
    childProcess.spawn = mySpawn;
})();

Then the next time you run your application, before the uncaught exception's message you will see something like that: 然后,下次运行应用程序时,在未捕获的异常消息之前,您将看到类似以下内容:

spawn called
{ '0': 'hg',
  '1': [],
  '2':
   { cwd: '/* omitted */',
     env: { IP: '0.0.0.0' },
     args: [] } }

In this way you can easily know which command actually is executed and then you can find out why nodejs cannot find the executable to fix the problem. 通过这种方式,您可以轻松知道实际执行了哪个命令,然后可以找出为什么nodejs无法找到可执行程序来解决该问题。


#4楼

In my case, I was getting this error thrown due to the necessary dependent system resources not being installed. 就我而言,由于未安装必要的依赖系统资源而引发此错误。

More specifically, I have a NodeJS app that is utilizing ImageMagick. 更具体地说,我有一个使用ImageMagick的NodeJS应用程序。 Despite having the npm package installed, the core Linux ImageMagick was not installed. 尽管已安装了npm软件包,但尚未安装核心Linux ImageMagick。 I did an apt-get to install ImageMagick and after that all worked great! 我做了一个易于安装ImageMagick的工作,之后一切都变好了!


#5楼

对于任何人谁可能偶然发现了这一点,如果所有其他的答案不帮助你,你是在Windows上,知道的是,目前有一个很大的问题, spawn在Windows和PATHEXT环境变量,可能会导致某些呼叫产卵到不行视关于如何安装目标命令。


#6楼

Windows solution: Replace spawn with node-cross-spawn . 的Windows解决方案:更换spawn与节点交叉产卵 。 For instance like this at the beginning of your app.js: 例如在您的app.js开头这样的例子:

(function() {
    var childProcess = require("child_process");
    childProcess.spawn = require('cross-spawn');
})(); 

你可能感兴趣的:(node.js,debugging,error-handling,child-process,spawn)