首页 文章

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

提问于
浏览

17 回答

  • 176

    我遇到了同样的问题,但我找到了一种简单的方法来解决它 . 如果程序已被用户添加到PATH(例如,正常的系统命令工作),则似乎是 spawn() 错误 .

    要解决此问题,您可以使用which模块( npm install --save which ):

    // Require which and child_process
    const which = require('which');
    const spawn = require('child_process').spawn;
    // Find npm in PATH
    const npm = which.sync('npm');
    // Execute
    const noErrorSpawn = spawn(npm, ['install']);
    
  • 24

    对于Windows上的ENOENT,https://github.com/nodejs/node-v0.x-archive/issues/2318#issuecomment-249355505修复它 .

    例如用以下代码替换spawn('npm',[' - v'],{stdio:'inherit'}):

    • 对于所有node.js版本:
    spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['-v'], {stdio: 'inherit'})
    
    • for node.js 5.x及更高版本:
    spawn('npm', ['-v'], {stdio: 'inherit', shell: true})
    
  • 14

    步骤1:确保以正确的方式调用spawn

    首先,查看docs for child_process.spawn( command, args, options )

    使用给定命令启动新进程,使用args中的命令行参数 . 如果省略,则args默认为空数组 . 第三个参数用于指定其他选项,默认为:{cwd:undefined,env:process.env}使用env指定新进程可见的环境变量,默认为process.env .

    Ensure you are not putting any command line arguments in command and the whole spawn call is valid . 继续下一步 .

    步骤2:识别发出错误事件的事件 Launcher

    在您的源代码中搜索每次调用 spawnchild_process.spawn ,即

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

    并在那里附加一个'error'事件的事件监听器,这样你就会注意到将它作为'Unhandled'抛出的确切事件 Launcher . 调试后,可以删除该处理程序 .

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

    执行,你应该得到你的'错误'监听器注册的文件路径和行号 . 就像是:

    /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)
    

    如果前两行仍然是

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

    再做这一步,直到他们不这样做 . You must identify the listener that emits the error before going on next step.

    步骤3:确保设置了环境变量$ PATH

    有两种可能的情况:

    • 您依赖于默认的 spawn 行为,因此子进程环境将与 process.env 相同 .

    • 您明确地在 options 参数上将 env 对象传递给 spawn .

    In both scenarios, you must inspect the PATH key on the environment object that the spawned child process will use.

    方案1的示例

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

    方案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 (i.e., it's undefined) will cause spawn to emit the ENOENT error ,因为除非它是可执行文件的绝对路径,否则无法找到任何 command .

    When PATH is correctly set, proceed to next step. 它应该是目录或目录列表 . 最后一种情况是通常的 .

    步骤4:确保命令存在于PATH中定义的目录中

    Spawn may emit the ENOENT error if the filename command (i.e, 'some-command') does not exist in at least one of the directories defined on PATH.

    找到 command 的确切位置 . 在大多数Linux发行版中,这可以通过带有 which 命令的终端来完成 . 它将告诉您可执行文件的绝对路径(如上所述),或告诉您是否找不到它 .

    命令为 found 时的使用示例及其输出

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

    命令为 not found 时的使用示例及其输出

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

    miss-installed programs are the most common cause for a not found command. 如果需要,请参阅每个命令文档并进行安装 .

    When command is a simple script file ensure it's accessible from a directory on the PATH. 如果不是,请将其移至一个或链接到它 .

    一旦确定 PATH 已正确设置并且可以从中访问 command ,您应该能够在不抛出 spawn ENOENT 的情况下生成子进程 .

  • 88

    Windows解决方案:将 spawn 替换为node-cross-spawn . 例如,在app.js的开头就像这样:

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

    @ laconbass的回答帮助了我,可能是最正确的 .

    我来到这里是因为我错误地使用了spawn . 举个简单的例子:

    这是不正确的:

    const s = cp.spawn('npm install -D suman', [], {
        cwd: root
    });
    

    这是不正确的:

    const s = cp.spawn('npm', ['install -D suman'], {
        cwd: root
    });
    

    this is correct:

    const s = cp.spawn('npm', ['install','-D','suman'], {
        cwd: root
    });
    

    但是,我建议这样做:

    const s = cp.spawn('bash');
    s.stdin.end(`cd "${root}" && npm install -D suman`);
    s.once('exit', code => {
       // exit
    });
    

    这是因为只要安装了bash, cp.on('exit', fn) 事件将始终触发,否则,如果我们直接启动'npm',如果我们以第一种方式使用它,则 cp.on('error', fn) 事件可能会先触发 .

  • 16

    我在Windows 8中遇到了同样的错误 . 问题是因为缺少系统路径的环境变量 . 将“C:\ Windows \ System32 \”值添加到系统PATH变量中 .

  • 1

    我找到了一种特别简单的方法来了解其根本原因:

    Error: spawn ENOENT
    

    这个错误的问题是,错误消息中几乎没有信息告诉你调用站点在哪里,即找不到哪个可执行文件/命令,特别是当你有一个很大的代码库,其中有很多spawn调用 . 另一方面,如果我们知道导致错误的确切命令,那么我们可以按照@laconbass' answer来解决问题 .

    我找到了一种非常简单的方法来发现哪个命令导致问题,而不是像@laconbass'回答中建议的那样在代码中的任何地方添加事件监听器 . 关键的想法是用包装器包装原始spawn调用,该包装器打印发送到spawn调用的参数 .

    这是包装函数,将它放在 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;
    })();
    

    然后,下次运行应用程序时,在未捕获的异常消息之前,您将看到类似的内容:

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

    通过这种方式,您可以轻松地知道实际执行了哪个命令,然后您可以找出为什么nodejs找不到可执行文件来解决问题 .

  • 1

    使用 require('child_process').exec 而不是spawn来获取更具体的错误消息!

    例如:

    var exec = require('child_process').exec;
    var commandStr = 'java -jar something.jar';
    
    exec(commandStr, function(error, stdout, stderr) {
      if(error || stderr) console.log(error || stderr);
      else console.log(stdout);
    });
    
  • 0

    在我的情况下,由于没有安装必要的依赖系统资源,我得到了这个错误 .

    更具体地说,我有一个使用ImageMagick的NodeJS应用程序 . 尽管安装了npm软件包,但未安装核心Linux ImageMagick . 我做了一个apt-get来安装ImageMagick,之后一切都很棒!

  • 0

    在运行我的测试用例时,我也遇到了这个恼人的问题,所以我尝试了很多方法来解决它 . 但对我有用的方法是 run your test runner from the directory which contains your main file ,其中包括你的 nodejs spawn 函数:

    nodeProcess = spawn('node',params, {cwd: '../../node/', detached: true });
    

    例如,这个 file name is test.js ,所以只是 move to the folder which contains it . 就我而言,它是这样的测试文件夹:

    cd root/test/
    

    然后从 run your test runner 在我的情况下它的摩卡,所以它将是这样的:

    mocha test.js
    

    我浪费了一天以上的时间来弄明白 . 请享用!!

  • 1

    如果@DanielImfeld pointed it,如果在选项中指定"cwd",则会抛出ENOENT,但给定目录不存在 .

  • 21

    如果您使用的是Windows Node.js在处理引号时会做一些有趣的事情,这可能会导致您发出一个您知道在控制台中运行的命令,但在Node中运行时则不会 . 例如,以下应该工作:

    spawn('ping', ['"8.8.8.8"'], {});
    

    但失败了 . 有一个奇妙的未记录的选项 windowsVerbatimArguments 用于处理引号/类似似乎可以做到这一点,只需确保将以下内容添加到您的opts对象:

    const opts = {
        windowsVerbatimArguments: true
    };
    

    你的命令应该重新开始 .

    spawn('ping', ['"8.8.8.8"'], { windowsVerbatimArguments: true });
    
  • 0

    对于任何可能偶然发现这一点的人,如果所有其他答案都没有帮助并且您在Windows上,请知道当前有a big issue with spawn on WindowsPATHEXT 环境变量可能导致某些调用生成不起作用,具体取决于目标命令的方式安装 .

  • 0

    C:\Windows\System32\ 添加到 path 环境变量中 .

    步骤

    • 转到我的电脑和 property

    • 单击高级设置

    • 然后是环境变量

    • 选择 Path ,然后单击编辑

    • 如果不存在,请粘贴以下内容: C:\Windows\System32\

    • 关闭命令提示符

    • 运行要运行的命令

    Windows 8 Environment variables screenshot

  • 1

    如果它不是节点模块,请确保要安装的模块或命令的完整路径

  • 11

    我的解决方案

    var spawn = require('child_process').spawn;
    
    const isWindows = /^win/.test(process.platform); 
    
    spawn(isWindows ? 'twitter-proxy.cmd' : 'twitter-proxy');
    spawn(isWindows ? 'http-server.cmd' : 'http-server');
    
  • 6

    尝试从Debian Linux系统上的VS Code编辑器中调试node.js程序时出现此错误 . 我注意到在Windows上同样的功能正常 . 之前给出的解决方案没有多大帮助,因为我没有编写任何“spawn”命令 . 违规代码大概是由Microsoft编写的,隐藏在VS Code程序的引擎盖下 .

    接下来我注意到node.js在Windows上被称为节点,但在Debian上(可能是在基于Debian的系统上,如Ubuntu),它被称为nodejs . 所以我创建了一个别名 - 从根终端,我跑了

    ln -s / usr / bin / nodejs / usr / local / bin / node

    这解决了这个问题 . 相同或类似的过程可能适用于其中node.js被称为nodejs的其他情况,但是您运行的程序期望它被称为节点,反之亦然 .

相关问题