it-swarm.com.ru

Как мне отладить "Ошибка: вызов ENOENT" на node.js?

Когда я получаю следующую ошибку:

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)

Какую процедуру я могу выполнить, чтобы исправить это?

Примечание автора: множество проблем с этой ошибкой побудили меня опубликовать этот вопрос для будущих ссылок.

Похожие вопросы:

248
laconbass

Я нашел очень простой способ понять причину:

Error: spawn ENOENT

Проблема этой ошибки в том, что в сообщении об ошибке действительно мало информации, чтобы сказать вам, где находится сайт вызова, т.е. какой исполняемый файл/команда не найден, особенно если у вас большая кодовая база, где много вызовов вызова , С другой стороны, если мы знаем точную команду, которая вызывает ошибку, тогда мы можем следовать @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 не может найти исполняемый файл для решения проблемы.

184
Jiaji Zhou

Шаг 1: Убедитесь, что spawn назван правильно

Сначала просмотрите документы для child_process.spawn (команда, аргументы, опции) :

Запускает новый процесс с заданной command, с аргументами командной строки в args. Если опущен, args по умолчанию равен пустому массиву.

Третий аргумент используется для указания дополнительных опций, по умолчанию это:

{ cwd: undefined, env: process.env }

Используйте env, чтобы указать переменные среды, которые будут видны новому процессу, по умолчанию process.env.

Убедитесь, что вы не вводите аргументы командной строки в command, и весь вызов spawn действителен. Перейдите к следующему шагу.

Шаг 2: Определите источник событий, который генерирует событие ошибки

Выполняйте поиск в исходном коде для каждого вызова spawn или child_process.spawn, т.е.

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

и прикрепите там прослушиватель событий для события error, чтобы вы точно заметили Emitter, который выбрасывает его как «Unhandled». После отладки этот обработчик может быть удален.

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

сделайте этот шаг снова, пока их нет. Прежде чем перейти к следующему шагу, вы должны определить прослушиватель, который выдает ошибку.

Шаг 3. Убедитесь, что установлена ​​переменная среды $PATH

Есть два возможных сценария:

  1. Вы полагаетесь на поведение по умолчанию spawn, поэтому дочерняя среда процесса будет такой же, как process.env.
  2. Вы просто передаете объект envspawn в аргументе options.

В обоих сценариях вы должны проверить ключ PATH на объекте среды, который будет использоваться порожденным дочерним процессом.

Пример для сценария 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 });

Отсутствие PATH (т. Е. Это undefined) приведет к тому, что spawn испустит ошибку ENOENT, так как невозможно будет найти любую command, если это не абсолютный путь к исполняемому файлу.

Когда PATH установлен правильно, переходите к следующему шагу. Это должен быть каталог или список каталогов. Последний случай обычный.

Шаг 4. Убедитесь, что command существует в каталоге из тех, которые определены в PATH

Spawn может выдавать ошибку ENOENT, если имя файла command (т.е., some-command) не существует хотя бы в одном из каталогов, определенных в PATH.

Найдите точное место command. В большинстве дистрибутивов Linux это можно сделать из терминала с помощью команды which. Он сообщит вам абсолютный путь к исполняемому файлу (как выше) или сообщит, если он не найден.

Пример использования которого и его вывод, когда команда found

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

Пример использования которого и его вывод, когда команда не найдена

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

пропущенные программы являются наиболее распространенной причиной команды не найден. При необходимости обратитесь к документации по каждой команде и установите ее.

Когда команда представляет собой простой файл сценария, убедитесь, что он доступен из каталога на PATH. Если это не так, либо переместите его к одному, либо сделайте ссылку на него.

Как только вы определите, что PATH правильно установлен и command доступен из него, вы сможете порождать свой дочерний процесс без запуска spawn ENOENT.

93
laconbass

Как указывало @DanielImfeld , ENOENT будет выброшен, если вы укажете "cwd" в опциях, но данный каталог не существует.

27
Leeroy Brun

Решение для Windows: замените spawn на node-cross-spawn . Например, вот так в начале вашего app.js:

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

Ответ @ laconbass помог мне и, вероятно, является наиболее правильным.

Я пришел сюда, потому что я использовал spawn неправильно . В качестве простого примера:

это неверно:

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

это неверно:

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

это правильно:

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

это потому, что тогда событие cp.on('exit', fn) будет всегда запускаться, пока установлен bash, в противном случае событие cp.on('error', fn) может сработать первым, если мы используем его первым способом, если мы запустим 'npm' напрямую. 

18
Alexander Mills

Для тех, кто может наткнуться на это, если все остальные ответы не помогают, и вы находитесь в Windows, знайте, что в настоящее время большая проблема с spawn в Windows и переменной среды PATHEXT, которая может вызывать определенные вызовы не работать в зависимости от того, как установлена ​​целевая команда.

15
Alex Turpin

Для ENOENT в Windows, https://github.com/nodejs/node-v0.x-archive/issues/2318#issuecomment-249355505 исправить это.

например заменить spawn ('npm', ['-v'], {stdio: 'наследовать'}) на:

  • для всей версии node.js:

    spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['-v'], {stdio: 'inherit'})
    
  • для node.js 5.x и выше:

    spawn('npm', ['-v'], {stdio: 'inherit', Shell: true})
    
13
Li Zheng

В моем случае я получал эту ошибку из-за того, что не были установлены необходимые зависимые системные ресурсы.

В частности, у меня есть приложение NodeJS, которое использует ImageMagick. Несмотря на то, что был установлен пакет npm, ядро ​​Linux ImageMagick не было установлено. Я сделал apt-get для установки ImageMagick, и после этого все работало отлично!

6
PromInc

Убедитесь, что модуль для выполнения установлен или полный путь к команде, если это не модуль узла 

1
Dalton

Я столкнулся с той же проблемой, но нашел простой способ ее исправить . Похоже, это ошибки spawn(), если программа была добавлена ​​пользователем в PATH (например, работают обычные системные команды).

Чтобы это исправить, вы можете использовать модуль 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']);
1
Gum Joe

Я также проходил через эту досадную проблему, выполняя свои тестовые случаи, поэтому я попробовал много способов решить эту проблему. Но способ, который мне подходит, заключается в том, чтобы запустить ваш тестовый прогон из каталога, который содержит ваш основной файл который включает в себя вашу nodejs spawn функцию примерно так:

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

Например, это имя файла test.js , поэтому просто перейдите в папку, в которой он находится . В моем случае это тестовая папка:

cd root/test/

затем из запустите ваш тестовый бегун в моем случае это его мокко, так что это будет так:

mocha test.js

Я потратил больше одного дня, чтобы понять это. Наслаждаться!!

0
Rajkumar Bansal

Используйте 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
de Raad

решение в моем случае 

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');
0
Dan Alboteanu

Если вы работаете в 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
Joel B

Я получил ту же ошибку для Windows 8. Проблема в том, что отсутствует переменная среды вашего системного пути. Добавьте значение «C:\Windows\System32 \» в системную переменную PATH.

0
chayasan

Я получал эту ошибку при попытке отладки программы node.js из редактора кода VS в системе Debian Linux. Я заметил, что та же самая вещь работала хорошо на Windows. Решения, приведенные здесь ранее, не сильно помогли, потому что я не написал никаких команд "spawn". Оскорбительный код предположительно был написан Microsoft и спрятан под капотом программы VS Code.

Затем я заметил, что node.js называется node в Windows, но в Debian (и, вероятно, в системах на основе Debian, таких как Ubuntu) он называется nodejs. Итак, я создал псевдоним - из корневого терминала я запустил 

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

и это решило проблему. Эта же или аналогичная процедура, вероятно, будет работать в других случаях, когда ваш node.js называется nodejs, но вы запускаете программу, которая ожидает, что она будет называться node, или наоборот.

0
MTGradwell