Cómo depuro "Error: spawn ENOENT" en el nodo.js?


Cuando obtengo el siguiente 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)

¿Qué procedimiento puedo seguir para arreglarlo?

Nota del autor : Muchos problemas con este error me animaron a publicar esta pregunta para futuras referencias.

Preguntas Relacionadas:

Author: Community, 2014-12-29

16 answers

Encontré una manera fácil de tener la idea de la causa raíz de:

Error: spawn ENOENT

El problema de este error es que hay muy poca información en el mensaje de error para decirle dónde está el sitio de la llamada, es decir, qué ejecutable/comando no se encuentra, especialmente cuando tiene una gran base de código donde hay muchas llamadas de spawn. Por otro lado, si conocemos el comando exacto que causa el error entonces podemos seguir @laconbass' respuesta para solucionar el problema.

Encontré un una manera muy fácil de detectar qué comando causa el problema en lugar de agregar oyentes de eventos en todas partes en su código como se sugiere en la respuesta de @laconbass. La idea clave es envolver la llamada de spawn original con un wrapper que imprime los argumentos enviados a la llamada de spawn.

Aquí está la función wrapper, póngala en la parte superior del index.js o cualquiera que sea el script de inicio de su servidor.

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

Luego, la próxima vez que ejecute su aplicación, antes del mensaje de excepción no capturada verá algo así:

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

De esta manera puede saber fácilmente qué comando se ejecuta realmente y luego puede averiguar por qué nodejs no puede encontrar el ejecutable para solucionar el problema.

 174
Author: Jiaji Zhou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:54

Paso 1: Asegúrese de que spawn se llame de la manera correcta

Primero, revise los documentos para child_process.spawn (comando, argumentos, opciones ):

Lanza un nuevo proceso con el command dado, con argumentos de línea de comandos en args. Si se omite, args tiene por defecto un Array vacío.

El tercer argumento se utiliza para especificar opciones adicionales, que por defecto es:

{ cwd: undefined, env: process.env }

Use env para especificar variables de entorno que serán visible para el nuevo proceso, el valor predeterminado es process.env.

Asegúrese de que no está poniendo ningún argumento de línea de comandos en command y que toda la llamada spawn es válida. Proceda al siguiente paso.

Paso 2: Identificar el Emisor de eventos que emite el evento de error

Busque en su código fuente para cada llamada a spawn, o child_process.spawn, es decir,

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

Y adjunte allí un receptor de eventos para el evento 'error', para que se note el Emisor de eventos exacto que lo está lanzando como 'Unhandled'. Después de la depuración, ese controlador se puede eliminar.

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

Ejecute y debe obtener la ruta del archivo y el número de línea donde se registró su oyente de 'error'. Algo como:

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

Si las dos primeras líneas siguen siendo

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

Haga este paso de nuevo hasta que no lo sean. Debe identificar el oyente que emite el error antes de continuar con el siguiente paso.

Paso 3: Asegúrese de que la variable de entorno $PATH esté establecida

Hay dos posibles escenarios:

  1. Se basa en el comportamiento predeterminado spawn, por lo que el entorno del proceso hijo será el mismo que process.env.
  2. Estás pasando un objeto env a spawn en el argumento options.

En ambos escenarios, debe inspeccionar la tecla PATH en el objeto de entorno que utilizará el proceso hijo generado.

Ejemplo para el escenario 1

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

Ejemplo de escenario 2

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

La ausencia de PATH (es decir, es undefined) hará que spawn emita el error ENOENT , ya que no será posible localizar ningún command a menos que sea una ruta absoluta al archivo ejecutable.

Cuando PATH esté configurado correctamente, proceda al siguiente paso. debe ser un directorio, o una lista de directorios. El último caso es el de siempre.

Paso 4: Asegúrese de que command existe en un directorio de los definidos en PATH

Spawn puede emitir el error ENOENT si el nombre del archivo command (es decir, 'some-command') no existe en al menos uno de los directorios definidos en PATH.

Localice el lugar exacto de command. En la mayoría de las distribuciones de linux, esto se puede hacer desde una terminal con el comando which. Le dirá la ruta absoluta al archivo ejecutable (como arriba), o le dirá si no se encuentra.

Ejemplo de uso de cuál y su salida cuando un comando es encontrado

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

Ejemplo de uso del cual y su salida cuando un comando es no encontrado

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

Los programas mal instalados son la causa más común de un comando no encontrado. Consulte la documentación de cada comando si es necesario e instálela.

Cuando el comando es un archivo de script simple, asegúrese de que sea accesible desde un directorio en el PATH. Si no lo es, moverlo a uno o hacer un enlace a se.

Una vez que determine que PATH está correctamente configurado y command es accesible desde él, debería ser capaz de generar su proceso hijo sin spawn ENOENT ser lanzado.

 85
Author: laconbass,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-19 15:43:15

Como @DanielImfeld lo señaló, se lanzará ENOENT si especifica "cwd" en las opciones, pero el directorio dado no existe.

 23
Author: Leeroy Brun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:03:09

Solución de Windows: Reemplace spawnpor node-cross-spawn . Por ejemplo, al principio de tu aplicación.js:

(function() {
    var childProcess = require("child_process");
    childProcess.spawn = require('cross-spawn');
})(); 
 21
Author: Nilzor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-22 19:57:51

La respuesta de@laconbass me ayudó y es probablemente la más correcta.

Vine aquí porque estaba usando spawn incorrectamente. Como un simple ejemplo:

esto es incorrecto:

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

esto es incorrecto:

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

Esto es correcto:

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

Sin embargo, recomiendo hacerlo de esta manera:

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

Esto se debe a que entonces el evento cp.on('exit', fn) siempre se disparará, siempre y cuando bash esté instalado, de lo contrario, el evento cp.on('error', fn) podría dispararse primero, si lo usamos de la primera manera, si lanzamos 'npm' directamente.

 15
Author: Alexander Mills,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-19 06:12:40

Para cualquiera que pueda tropezar con esto, si todas las otras respuestas no ayudan y está en Windows, sepa que actualmente existe un gran problema con spawn en Windows y la variable de entorno PATHEXT que puede hacer que ciertas llamadas no funcionen dependiendo de cómo se instale el comando de destino.

 14
Author: Alex Turpin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-05 19:37:47

Para ENOENT en Windows, https://github.com/nodejs/node-v0.x-archive/issues/2318#issuecomment-249355505 solucionarlo.

Por ejemplo, reemplazar spawn ('npm', ['- v'], {stdio:' inherit'}) con:

  • Para todos los nodos.js version:

    spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['-v'], {stdio: 'inherit'})
    
  • Para nodo.js 5.x y posteriores:

    spawn('npm', ['-v'], {stdio: 'inherit', shell: true})
    
 8
Author: Li Zheng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-25 02:22:47

En mi caso, estaba obteniendo este error debido a que los recursos del sistema dependientes necesarios no se estaban instalando.

Más específicamente, tengo una aplicación NodeJS que está utilizando ImageMagick. A pesar de tener el paquete npm instalado, el núcleo de Linux ImageMagick no estaba instalado. Hice un apt-get para instalar ImageMagick y después de eso todo funcionó muy bien!

 6
Author: PromInc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-12 20:01:19

Me encontré con el mismo problema, pero encontré una manera sencilla de solucionarlo. Parecen ser errores spawn() si el programa ha sido agregado a la RUTA por el usuario (por ejemplo, los comandos normales del sistema funcionan).

Para arreglar esto, puede usar el módulo 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
Author: Gum Joe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-06-26 06:59:35

Asegúrese de que el módulo a ejecutar esté instalado o la ruta completa al comando si no es un módulo de nodo

 1
Author: Dalton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-25 20:50:14

Utilice require('child_process').exec en lugar de spawn para un mensaje de error más específico!

Por ejemplo:

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);
});
 1
Author: de Raad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-03 08:51:29

Estaba recibiendo este error al intentar depurar un nodo.programa js desde el editor de código VS en un sistema Debian Linux. Noté que lo mismo funcionaba bien en Windows. Las soluciones dadas anteriormente aquí no fueron de mucha ayuda porque no había escrito ningún comando "spawn". El código ofensivo fue supuestamente escrito por Microsoft y escondido bajo el capó del programa VS Code.

Luego me di cuenta de ese nodo.js se llama nodo en Windows pero en Debian (y presumiblemente en sistemas basados en Debian como Ubuntu) se llama nodejs. Así que creé un alias - desde un terminal raíz, corrí

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

Y esto resolvió el problema. El mismo procedimiento o un procedimiento similar probablemente funcionará en otros casos donde su nodo.js se llama nodejs pero está ejecutando un programa que espera que se llame node, o viceversa.

 0
Author: MTGradwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-28 00:20:10

Tengo el mismo error para Windows 8.El problema se debe a que falta una variable de entorno de la ruta de acceso del sistema . Añadir "C:\Windows\System32\" valor de la variable de ruta del sistema.

 0
Author: chayasan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-06 11:48:08

Si estás en el nodo de Windows.js hace algunos negocios divertidos al manejar comillas que pueden resultar en que usted emita un comando que sabe que funciona desde la consola, pero no cuando se ejecuta en el nodo. Por ejemplo, lo siguiente debería funcionar:

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

Pero falla. Hay una opción fantásticamente indocumentada windowsVerbatimArguments para manejar comillas / similares que parece hacer el truco, solo asegúrese de agregar lo siguiente a su objeto opts:

const opts = {
    windowsVerbatimArguments: true
};

Y su comando debe estar de vuelta en negocio.

 spawn('ping', ['"8.8.8.8"'], { windowsVerbatimArguments: true });
 0
Author: Joel B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-18 00:48:34

También estaba pasando por este molesto problema mientras ejecutaba mis casos de prueba, así que intenté muchas maneras de cruzarlo. Pero la forma en que funciona para mí es ejecutar su corredor de prueba desde el directorio que contiene su archivo principal que incluye su nodejs spawn función algo como esto:

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

Por ejemplo, este nombre de archivo es test.js , así que simplemente muévete a la carpeta que lo contiene. En mi caso, es una carpeta de prueba como esta:

cd root/test/

Luego de ejecuta tu test runner en mi caso es mocha así que será así:

mocha test.js

He perdido más de un día para averiguarlo. ¡Que lo disfrutes!!

 0
Author: Rajkumar Bansal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-13 08:21:53

Agregue C:\Windows\System32\ a la variable de entorno path.

Pasos

  1. Ir a mi equipo y propiedades

  2. Haga clic en Configuración avanzada

  3. Luego en Variables de entorno

  4. Seleccione Path y luego haga clic en editar

  5. Pegue lo siguiente si aún no está presente: C:\Windows\System32\

  6. Cierre el símbolo del sistema

  7. Ejecute el comando que desea ejecutar

Captura de pantalla de variables de entorno de Windows 8

 -1
Author: vmit dhawan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-08-31 20:09:03