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)
Note de l’auteur: de nombreux problèmes liés à cette erreur m’ont incité à poser cette question pour référence future.
Questions connexes:
J'ai trouvé un moyen particulièrement facile de se faire une idée de la cause fondamentale de:
Error: spawn ENOENT
Le problème de cette erreur est qu’il ya très peu d’informations dans le message d’erreur pour vous dire où se trouve le site d’appel, c’est-à-dire quel exécutable/commande n’est pas trouvé, en particulier lorsque vous avez une base de code volumineuse où il y a beaucoup d’appels spawn . D'autre part, si nous connaissons la commande exacte qui cause l'erreur, nous pouvons suivre @laconbass 'answer pour résoudre le problème.
J'ai trouvé un moyen très facile de repérer quelle commande posait le problème plutôt que d'ajouter des écouteurs d'événements partout dans votre code, comme suggéré dans la réponse de @laconbass. L'idée principale est d'encapsuler l'appel spawn d'origine avec un wrapper qui imprime les arguments envoyés à l'appel spawn.
Voici la fonction wrapper, placez-la en haut du index.js
ou quel que soit le script de démarrage de votre serveur.
(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;
})();
Ensuite, la prochaine fois que vous exécuterez votre application, avant le message de l'exception non capturée, vous verrez quelque chose comme ça:
spawn called
{ '0': 'hg',
'1': [],
'2':
{ cwd: '/* omitted */',
env: { IP: '0.0.0.0' },
args: [] } }
De cette façon, vous pouvez facilement savoir quelle commande est réellement exécutée, puis vous pouvez comprendre pourquoi nodejs ne peut pas trouver l'exécutable pour résoudre le problème.
spawn
est appelé de la bonne manièreTout d’abord, passez en revue les docs pour child_process.spawn (commande, arguments, options) :
Lance un nouveau processus avec la variable
command
donnée, avec des arguments de ligne de commande dansargs
. Si omis,args
est défini par défaut sur un tableau vide.Le troisième argument est utilisé pour spécifier des options supplémentaires, par défaut:
{ cwd: undefined, env: process.env }
Utilisez
env
pour spécifier les variables d’environnement qui seront visibles par le nouveau processus. La valeur par défaut estprocess.env
.
Assurez-vous de ne pas placer d'argument de ligne de commande dans command
et que l'appel spawn
dans son ensemble est valide. Passez à l'étape suivante.
Recherchez votre code source pour chaque appel à spawn
ou child_process.spawn
, c.-à-d.
spawn('some-command', [ '--help' ]);
et attachez-y un écouteur d’événement pour l’événement «erreur», afin que vous remarquiez l’émetteur d’événement exact qui le renvoie comme «non géré». Après le débogage, ce gestionnaire peut être supprimé.
spawn('some-command', [ '--help' ])
.on('error', function( err ){ throw err })
;
Exécutez-le et vous devriez obtenir le chemin du fichier et le numéro de ligne où votre écouteur "erreur" a été enregistré. Quelque chose comme:
/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 les deux premières lignes sont encore
events.js:72
throw er; // Unhandled 'error' event
refaites cette étape jusqu'à ce qu'ils ne le soient pas. Vous devez identifier l'écouteur qui émet l'erreur avant de passer à l'étape suivante.
$PATH
est définieIl y a deux scénarios possibles:
spawn
. L'environnement du processus enfant sera donc identique à process.env
.env
à spawn
sur l'argument options
.Dans les deux scénarios, vous devez inspecter la clé PATH
sur l'objet d'environnement utilisé par le processus enfant engendré.
Exemple pour le scénario 1
// inspect the PATH key on process.env
console.log( process.env.PATH );
spawn('some-command', ['--help']);
Exemple pour le scénario 2
var env = getEnvKeyValuePairsSomeHow();
// inspect the PATH key on the env object
console.log( env.PATH );
spawn('some-command', ['--help'], { env: env });
L'absence de PATH
(c'est-à-dire, c'est undefined
) fera que spawn
émettra l'erreur ENOENT
, car il ne sera pas possible de localiser un command
sauf s'il s'agit d'un chemin absolu vers le fichier exécutable.
Lorsque PATH
est correctement défini, passez à l'étape suivante. Il devrait s'agir d'un répertoire ou d'une liste de répertoires. Le dernier cas est l'habituel.
command
existe dans un répertoire de ceux définis dans PATH
Spawn peut émettre l'erreur ENOENT
si le nom de fichier command
(c'est-à-dire 'une-commande') n'existe pas dans au moins un des répertoires définis sur PATH
.
Localisez le lieu exact de command
. Sur la plupart des distributions Linux, cela peut être fait depuis un terminal avec la commande which
. Il vous indiquera le chemin absolu du fichier exécutable (comme ci-dessus), ou vous indiquera s'il est introuvable.
Exemple d'utilisation et de son résultat lorsqu'une commande est trouvé
> which some-command
some-command is /usr/bin/some-command
Exemple d'utilisation et de son résultat lorsqu'une commande est introuvable
> which some-command
bash: type: some-command: not found
Les programmes miss-installés sont la cause la plus courante d'une commande non trouvée. Reportez-vous à la documentation de chaque commande si nécessaire et installez-la.
La commande When est un simple fichier script garantissant qu'il est accessible depuis un répertoire de la variable PATH
. Si ce n'est pas le cas, déplacez-le ou créez un lien vers celui-ci.
Une fois que vous avez déterminé que PATH
est correctement défini et que command
est accessible à partir de celle-ci, vous devriez pouvoir générer votre processus enfant sans que spawn ENOENT
soit lancé.
Comme @DanielImfeld l'a souligné , ENOENT sera lancé si vous spécifiez "cwd" dans les options, mais le répertoire donné n'existe pas.
Solution Windows: remplacez spawn
par node-cross-spawn . Par exemple, comme ceci au début de votre app.js:
(function() {
var childProcess = require("child_process");
childProcess.spawn = require('cross-spawn');
})();
La réponse de @ laconbass m'a aidée et est probablement la plus correcte.
Je suis venu ici parce que j’utilisais spawn de manière incorrecte… .. À titre d’exemple simple:
Ceci est une erreur:
const s = cp.spawn('npm install -D suman', [], {
cwd: root
});
Ceci est une erreur:
const s = cp.spawn('npm', ['install -D suman'], {
cwd: root
});
c'est correct:
const s = cp.spawn('npm', ['install','-D','suman'], {
cwd: root
});
cependant, je vous recommande de le faire de cette façon:
const s = cp.spawn('bash');
s.stdin.end(`cd "${root}" && npm install -D suman`);
s.once('exit', code => {
// exit
});
cela est dû au fait que l'événement cp.on('exit', fn)
sera toujours déclenché, tant que bash est installé, sinon l'événement cp.on('error', fn)
pourrait se déclencher en premier, si nous l'utilisons de la première façon, si nous lançons directement 'npm'.
Pour tous ceux qui pourraient tomber sur cela, si toutes les autres réponses ne vous aident pas et que vous êtes sur Windows, sachez qu'il existe actuellement un gros problème avec spawn
sous Windows et la variable d'environnement PATHEXT
pouvant entraîner certains appels spawn ne fonctionnera pas en fonction de l’installation de la commande cible.
Pour ENOENT sous Windows, https://github.com/nodejs/node-v0.x-archive/issues/2318#issuecomment-249355505 corrigez-le.
par exemple. remplace spawn ('npm', ['-v'], {stdio: 'inherit'}) par:
pour toutes les versions de node.js:
spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['-v'], {stdio: 'inherit'})
pour node.js 5.x et versions ultérieures:
spawn('npm', ['-v'], {stdio: 'inherit', Shell: true})
Dans mon cas, cette erreur s'est produite parce que les ressources système dépendantes nécessaires n'ont pas été installées.
Plus précisément, j'ai une application NodeJS qui utilise ImageMagick. Bien que le paquet npm soit installé, le noyau Linux ImageMagick n'était pas installé. J'ai fait un apt-get pour installer ImageMagick et ensuite tout a bien fonctionné!
Assurez-vous que le module à exécuter est installé ou le chemin complet de la commande s'il ne s'agit pas d'un module de noeud.
Je rencontrais le même problème, mais j’ai trouvé un moyen simple de le résoudre . Il semble y avoir des erreurs spawn()
si le programme a été ajouté à PATH par l’utilisateur (par exemple, les commandes système normales fonctionnent).
Pour résoudre ce problème, vous pouvez utiliser le quel module (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']);
Je passais également par ce problème ennuyeux lors de l’exécution de mes cas de test, j’ai donc essayé de nombreuses manières de le résoudre. Mais la façon dont cela fonctionne pour moi est de lancer votre programme d’essai à partir du répertoire qui contient votre fichier principal qui contient votre nodejs spawn function quelque chose comme ceci:
nodeProcess = spawn('node',params, {cwd: '../../node/', detached: true });
Par exemple, le nom de fichier est test.js , donc déplacez simplement vers le dossier qui le contient . Dans mon cas, c'est un dossier de test comme ceci:
cd root/test/
puis à partir de lancez votre coureur de test dans mon cas, son moka sera le suivant:
mocha test.js
J'ai passé plus d'une journée à comprendre. Prendre plaisir!!
Utilisez require('child_process').exec
au lieu de spawn pour un message d'erreur plus spécifique!
par exemple:
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);
});
solution dans mon cas
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');
Si vous utilisez Windows Node.js, vous pouvez vous amuser avec des citations, ce qui peut vous obliger à exécuter une commande dont vous savez qu'il fonctionne à partir de la console, mais qui ne fonctionne pas dans Node. Par exemple, le devrait travail:
spawn('ping', ['"8.8.8.8"'], {});
mais échoue. Il existe une option fantastiquement non documentée windowsVerbatimArguments
pour la gestion des guillemets/similaires qui semble faire l'affaire, assurez-vous simplement d'ajouter ce qui suit à votre objet opts:
const opts = {
windowsVerbatimArguments: true
};
et votre commande devrait être de retour dans les affaires.
spawn('ping', ['"8.8.8.8"'], { windowsVerbatimArguments: true });
J'ai rencontré ce problème sous Windows, où appeler exec
et spawn
avec exactement la même commande (en omettant les arguments) fonctionnait correctement pour exec
(donc je savais que ma commande était sur $PATH
), mais spawn
donnerait ENOENT. Il s'est avéré que je devais simplement ajouter .exe
à la commande que j'utilisais:
import { exec, spawn } from 'child_process';
// This works fine
exec('p4 changes -s submitted');
// This gives the ENOENT error
spawn('p4');
// But this resolves it
spawn('p4.exe');
// Even works with the arguments now
spawn('p4.exe', ['changes', '-s', 'submitted']);
J'ai la même erreur pour Windows 8. Le problème est dû à une variable d'environnement de votre chemin système qui manque. Ajoutez la valeur "C:\Windows\System32 \" à votre variable système PATH.
J'avais cette erreur en essayant de déboguer un programme node.js depuis l'éditeur de code VS sur un système Linux Debian. J'ai remarqué que la même chose fonctionnait correctement sous Windows. Les solutions données précédemment n'étaient pas d'une grande aide car je n'avais écrit aucune commande "spawn". Le code incriminé a probablement été écrit par Microsoft et caché sous le capot du programme VS Code.
Ensuite, j'ai remarqué que node.js s'appelle node sous Windows, mais sous Debian (et vraisemblablement sur des systèmes Debian comme Ubuntu), il s'appelle nodejs. J'ai donc créé un alias - à partir d'un terminal root, j'ai exécuté
ln -s/usr/bin/nodejs/usr/local/bin/node
et cela a résolu le problème. La même procédure ou une procédure similaire fonctionnera vraisemblablement dans les autres cas où votre node.js s'appelle nodejs mais que vous exécutez un programme qui s'attend à ce qu'il s'appelle node ou inversement.