it-swarm.com.de

Wie debugge ich "Error: spawn ENOENT" auf node.js?

Wenn ich die folgende Fehlermeldung bekomme:

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)

Welches Verfahren kann ich befolgen, um das Problem zu beheben?

Author note: Viele Probleme mit diesem Fehler ermutigten mich, diese Frage für zukünftige Verweise zu veröffentlichen.

Verwandte Fragen:

248
laconbass

Ich habe einen besonders einfachen Weg gefunden, um die Ursache für Folgendes zu ermitteln:

Error: spawn ENOENT

Das Problem dieses Fehlers ist, dass in der Fehlermeldung nur sehr wenige Informationen enthalten sind, die angeben, wo sich die Aufrufstelle befindet, dh welche ausführbare Datei/welcher Befehl nicht gefunden wird, insbesondere wenn Sie eine große Codebasis haben, bei der viele Spawn-Aufrufe vorhanden sind . Wenn wir andererseits den genauen Befehl kennen, der den Fehler verursacht, können wir der Antwort von @laconbass folgen , um das Problem zu beheben.

Ich habe einen sehr einfachen Weg gefunden, um herauszufinden, welcher Befehl das Problem verursacht, anstatt Ereignis-Listener überall in Ihrem Code hinzuzufügen, wie in der Antwort von @laconbass vorgeschlagen. Die Schlüsselidee ist, den ursprünglichen Spawn-Aufruf mit einem Wrapper zu umschließen, der die an den Spawn-Aufruf gesendeten Argumente druckt.

Hier ist die Wrapper-Funktion. Platzieren Sie sie oben in index.js oder in das Startskript Ihres Servers.

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

Wenn Sie dann das nächste Mal Ihre Anwendung ausführen, wird vor der Meldung der nicht erfassten Ausnahme Folgendes angezeigt:

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

Auf diese Weise können Sie leicht feststellen, welcher Befehl tatsächlich ausgeführt wird, und Sie können herausfinden, warum nodejs die ausführbare Datei nicht finden kann, um das Problem zu beheben.

184
Jiaji Zhou

Schritt 1: Stellen Sie sicher, dass spawn der richtige Weg ist

Überprüfen Sie zunächst die Dokumente für child_process.spawn (Befehl, Argumente, Optionen) :

Startet einen neuen Prozess mit der angegebenen command, mit Befehlszeilenargumenten in args. Wenn nicht angegeben, verwendet args standardmäßig ein leeres Array.

Das dritte Argument wird verwendet, um zusätzliche Optionen anzugeben, die standardmäßig Folgendes angeben:

{ cwd: undefined, env: process.env }

Verwenden Sie env, um Umgebungsvariablen anzugeben, die für den neuen Prozess sichtbar sind. Der Standardwert ist process.env.

Stellen Sie sicher, dass Sie keine Befehlszeilenargumente in command einfügen und dass der gesamte spawn-Aufruf gültig ist. Fahren Sie mit dem nächsten Schritt fort.

Schritt 2: Identifizieren Sie den Ereignissender, der das Fehlerereignis ausgibt

Suchen Sie in Ihrem Quellcode nach jedem Aufruf von spawn oder child_process.spawn, d. H.

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

und fügen Sie dort einen Ereignis-Listener für das 'error' -Ereignis an, so dass Sie genau den Event-Emitter bemerken, der das Ereignis als 'Unhandled' auslöst. Nach dem Debuggen kann dieser Handler entfernt werden.

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

Wenn Sie ausführen, sollten Sie den Dateipfad und die Zeilennummer erhalten, in der Ihr Fehlerlistener registriert wurde. So etwas wie:

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

Wenn die ersten beiden Zeilen noch stehen

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

wiederholen Sie diesen Schritt, bis sie es nicht tun. Sie müssen den Listener identifizieren, der den Fehler ausgibt, bevor Sie mit dem nächsten Schritt fortfahren.

Schritt 3: Stellen Sie sicher, dass die Umgebungsvariable $PATH eingestellt ist

Es gibt zwei mögliche Szenarien:

  1. Sie verlassen sich auf das Standardverhalten von spawn, daher entspricht die untergeordnete Prozessumgebung der von process.env.
  2. Sie übergeben explizit ein env-Objekt an spawn im Argument options.

In beiden Szenarien müssen Sie den Schlüssel PATH des Umgebungsobjekts überprüfen, das der erzeugte untergeordnete Prozess verwendet.

Beispiel für Szenario 1

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

Beispiel für Szenario 2

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

Das Fehlen von PATH (d. H., Es ist undefined) führt dazu, dass spawn den ENOENT-Fehler ausgibt, da es nicht möglich ist, command zu finden, es sei denn, dies ist ein absoluter Pfad zur ausführbaren Datei.

Wenn PATH richtig eingestellt ist, fahren Sie mit dem nächsten Schritt fort. Es sollte ein Verzeichnis oder eine Liste von Verzeichnissen sein. Letzter Fall ist das übliche.

Schritt 4: Stellen Sie sicher, dass command in einem Verzeichnis der in PATH definierten Verzeichnisse vorhanden ist.

Spawn gibt möglicherweise den Fehler ENOENT aus, wenn der Dateiname command (d. H. 'Some-command') nicht in mindestens einem der in PATH definierten Verzeichnisse vorhanden ist.

Suchen Sie den genauen Ort von command. Bei den meisten Linux-Distributionen kann dies von einem Terminal aus mit dem Befehl which ausgeführt werden. Es zeigt Ihnen den absoluten Pfad zur ausführbaren Datei (wie oben) oder gibt an, ob sie nicht gefunden wurde.

Beispiel für die Verwendung und deren Ausgabe, wenn ein Befehl found ist}

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

Beispiel für die Verwendung und deren Ausgabe, wenn ein Befehl nicht gefunden wurde

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

fehlinstallierte Programme sind die häufigste Ursache für einen nicht gefunden Befehl. Lesen Sie ggf. die Dokumentation zu den Befehlen und installieren Sie sie.

Der Befehl When ist eine einfache Skriptdatei und muss über ein Verzeichnis auf der Variable PATH erreichbar sein. Wenn dies nicht der Fall ist, verschieben Sie es entweder zu einem oder erstellen Sie einen Link.

Wenn Sie festgestellt haben, dass PATH richtig eingestellt ist und command von dort aus zugänglich ist, sollten Sie in der Lage sein, Ihren untergeordneten Prozess zu starten, ohne dass spawn ENOENT ausgelöst wird.

93
laconbass

Wie @DanielImfeld darauf hinweist wird ENOENT ausgelöst, wenn Sie in den Optionen "cwd" angeben, das angegebene Verzeichnis jedoch nicht vorhanden ist.

27
Leeroy Brun

Windows-Lösung: Ersetzen Sie spawn durch node-cross-spawn . Zum Beispiel wie folgt am Anfang Ihrer app.js:

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

@ laconbass's Antwort hat mir geholfen und ist wahrscheinlich am richtigsten.

Ich bin hierher gekommen, weil ich Spawn falsch verwendet habe ... Als einfaches Beispiel:

Das ist falsch:

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

Das ist falsch:

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

das ist richtig:

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

ich empfehle es jedoch so:

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

dies liegt daran, dass dann das cp.on('exit', fn) -Ereignis immer ausgelöst wird, solange bash installiert ist. Andernfalls wird das cp.on('error', fn) -Ereignis zuerst ausgelöst, wenn wir es auf die erste Weise verwenden, wenn 'npm' direkt gestartet wird. 

18
Alexander Mills

Für alle, die darauf stoßen könnten, wenn alle anderen Antworten nicht hilfreich sind und Sie sich unter Windows befinden, sollten Sie wissen, dass derzeit ein großes Problem mit spawn unter Windows und der Umgebungsvariable PATHEXT vorliegt, die dazu führen können, dass bestimmte Aufrufe auftreten nicht funktionieren, je nachdem, wie der Zielbefehl installiert ist.

15
Alex Turpin

Für ENOENT unter Windows https://github.com/nodejs/node-v0.x-archive/issues/2318#issuecomment-249355505 reparieren.

z.B. ersetze spawn ('npm', ['-v'], {stdio: 'erben'}) durch:

  • für alle node.js-Version:

    spawn(/^win/.test(process.platform) ? 'npm.cmd' : 'npm', ['-v'], {stdio: 'inherit'})
    
  • für node.js 5.x und höher:

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

In meinem Fall wurde mir dieser Fehler angezeigt, da die erforderlichen abhängigen Systemressourcen nicht installiert waren.

Genauer gesagt, ich habe eine NodeJS-App, die ImageMagick verwendet. Obwohl das npm-Paket installiert wurde, wurde der Linux ImageMagick-Kern nicht installiert. Ich habe apt-get installiert, um ImageMagick zu installieren und danach hat alles super funktioniert!

6
PromInc

Stellen Sie sicher, dass das auszuführende Modul installiert ist oder den vollständigen Pfad zum Befehl, wenn es kein Knotenmodul ist 

1
Dalton

Ich bin auf dasselbe Problem gestoßen, aber ich habe einen einfachen Weg gefunden, um das Problem zu beheben ... Es scheint ein spawn()-Fehler zu sein, wenn das Programm vom Benutzer zum PATH hinzugefügt wurde (beispielsweise funktionieren normale Systembefehle).

Um dies zu beheben, können Sie das Modul which (npm install --save which) verwenden:

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

Ich habe dieses nervige Problem auch während der Ausführung meiner Testfälle durchgemacht, also habe ich viele Möglichkeiten ausprobiert, um es zu vermitteln. Der Weg für mich ist jedoch: Führen Sie Ihren Testläufer aus dem Verzeichnis aus, in dem sich Ihre Hauptdatei befindet, das Ihre nodejs spawn-Funktion enthält.

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

Beispiel: Dateiname ist test.js, also nur in den Ordner verschieben, in dem sich die Datei befindet. In meinem Fall ist es ein Testordner wie folgt:

cd root/test/

dann von führe deinen Testläufer in meinem Fall seinen Mokka, also wird es so sein:

mocha test.js

Ich habe meinen mehr als einen Tag verschwendet, um es herauszufinden. Genießen!!

0
Rajkumar Bansal

Verwenden Sie require('child_process').exec anstelle von Spawn für eine spezifischere Fehlermeldung! 

zum Beispiel:

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

lösung in meinem Fall 

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

Wenn Sie sich mit Windows Node.js beschäftigen, führt die Handhabung von Anführungszeichen, die dazu führen können, dass Sie einen Befehl ausgeben, von dem Sie wissen, dass er von der Konsole aus funktioniert, eine witzige Sache aus, nicht jedoch, wenn er in Node ausgeführt wird. Zum Beispiel sollte soll funktionieren:

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

aber scheitert. Es gibt eine fantastisch undokumentierte Option windowsVerbatimArguments für die Handhabung von Anführungszeichen/Ähnlichem, die den Trick zu erfüllen scheint. Stellen Sie sicher, dass Sie Ihrem opts-Objekt Folgendes hinzufügen:

const opts = {
    windowsVerbatimArguments: true
};

und Ihr Befehl sollte wieder im Geschäft sein.

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

Ich hatte dieses Problem unter Windows, wo das Aufrufen von exec und spawn mit genau demselben Befehl (ohne Argumente) gut für exec funktionierte (daher wusste ich, dass mein Befehl auf $PATH lag), aber spawn würde ENOENT geben. Es stellte sich heraus, dass ich nur .exe an den Befehl anhängen musste, den ich verwendete:

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']);
0
MostlyArmless

Ich habe den gleichen Fehler für Windows 8. Das Problem liegt daran, dass eine Umgebungsvariable Ihres Systempfads fehlt. Fügen Sie Ihrer System-PATH-Variablen den Wert "C:\Windows\System32 \" hinzu.

0
chayasan

Ich habe diese Fehlermeldung erhalten, als ich versuchte, ein node.js-Programm aus dem VS-Code-Editor auf einem Debian-Linux-System zu debuggen. Ich habe bemerkt, dass das Gleiche unter Windows funktioniert hat. Die zuvor angegebenen Lösungen waren keine große Hilfe, da ich keine "Spawn" -Befehle geschrieben hatte. Der beleidigende Code wurde vermutlich von Microsoft geschrieben und unter der Kapuze des VS-Code-Programms versteckt.

Als Nächstes bemerkte ich, dass node.js unter Windows knoten heißt, aber unter Debian (und vermutlich auf Debian-basierten Systemen wie Ubuntu) heißt es nodejs. Also habe ich einen Alias ​​erstellt - von einem Root-Terminal bin ich gelaufen 

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

und das hat das Problem gelöst. Die gleiche oder eine ähnliche Prozedur wird vermutlich in anderen Fällen funktionieren, in denen Ihre node.js als nodejs bezeichnet wird, Sie jedoch ein Programm ausführen, von dem erwartet wird, dass es knoten heißt, oder umgekehrt.

0
MTGradwell