web-dev-qa-db-fra.com

L'utilisation de spawn de nodejs provoque les erreurs "option inconnue -" et "[Erreur: spawn ENOENT]"

J'essaie d'obtenir que spawn effectue un rm -rf node_modules suivi de npm install (sous Windows 7; n x commandes gracieusement fournies par un CygWin installé de manière transparente. Toutes les commandes n x sont résolues correctement en ligne de commande).

J'avais initialement ceci en utilisant exec, mais je voulais capturer les informations stdout/stderr telles qu'elles se présentaient, alors j'ai décidé d'utiliser spawn et de réécrire le code pour l'utiliser. Cependant, cela casse tout.

La commande rm, réécrite, est devenue ceci:

var spawn = require("child_process").spawn,
    child = spawn("rm", ["-rf", "node_modules"]);
child.stdout.on('data', function (data) { console.log(data.toString()); });
child.stderr.on('data', function (data) { console.log(data.toString()); });
child.on('error', function() { console.log(arguments); });

Cependant, cela génère l'erreur suivante:

rm: unknown option -- ,

Try `rm --help' for more information.

La commande npm, réécrite, est devenue ceci:

var spawn = require("child_process").spawn,
    child = spawn("npm", ["install"]);
child.stdout.on('data', function (data) { console.log(data.toString()); });
child.stderr.on('data', function (data) { console.log(data.toString()); });
child.on('error', function() { console.log(arguments); });

Cependant, cela génère l'erreur suivante:

{
  '0': {
    [Error: spawn ENOENT]
    code: 'ENOENT',
    errno: 'ENOENT',
    syscall: 'spawn'
  }
}

Comment puis-je faire en sorte que spawn exécute les mêmes commandes qui ont bien fonctionné en utilisant exec sans que cela génère des erreurs? Et pourquoi ça ne marche pas? En lisant l'API, http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options , semble suggérer que c'est précisément ainsi qu'on est supposé utiliser spawn ...

32

Après avoir essayé beaucoup de choses différentes, j’ai enfin jeté un œil à ce que "npm" est en réalité sur Windows. Il s’agit bien d’un script bash appelé npm, ainsi que d’un script de traitement par lots natif de Windows appelé npm.cmd .cmd, cela devrait être .bat, mais là vous l’avez). Le résolveur de commandes de Windows verra npm, remarquera qu'il ne s'agit pas d'un exécutable, voir npm.cmd, puis remarquera que IS est un exécutable, puis l'utilisera à la place. Ceci est utile lorsque vous êtes dans un terminal, mais spawn() ne fera pas une telle résolution: le transmettre npm le fera échouer car ce n'est pas un exécutable. Le passage de npm.cmd en tant que commande fonctionne cependant très bien.

(Aussi, vous ne savez pas pourquoi rm a échoué plus tôt, car cela fonctionne en fait correctement sans modifications que je puisse dire. Probablement mal interprété cela comme une partie du problème alors que ce n'était pas le cas.)

Ainsi: si vous rencontrez spawn en disant ENOENT dans Windows, lorsque la commande que vous essayez de déclencher fonctionne dans une invite de commande en clair, déterminez si la commande que vous appelez est un véritable exécutable ou s'il existe un fichier .bat/.cmd que la commande Invite sera "utilement" exécutée pour vous à la place. Si oui, engendre cela.

modifier

comme ce message reçoit toujours des votes positifs, un bon moyen de s’assurer que la commande fonctionne toujours est de l’amorcer à partir de process.platform, qui sera win32 pour Windows.

var npm = (process.platform === "win32" ? "npm.cmd" : "npm"),
    child = spawn(npm, ["install", ...]);
...
61

Je pense que cela peut être une sorte de cygwin gotcha. J'utilise Ubuntu 12.04 et j'essaie de dupliquer votre problème, mais cela fonctionne très bien pour moi. En bref, je ne vois rien que vous faites mal.

S'il se plaint de l'option, peut-être la scinder en plusieurs options comme ceci:

child = spawn("rm", ["-r", "-f", "node_modules"]);

C'est un peu ça, mais ça marche aussi sur Ubuntu 12.04. Vous pouvez essayer de simplement supprimer un seul fichier et voir si vous obtenez la même chose. 

child = spawn("rm", ["/home/username/Desktop/TestFile"]);

Si cela échoue toujours, alors vous savez que vous travaillez contre des trucs fous.

Vous pouvez même essayer d'exécuter une commande sans paramètre comme ceci:

child = spawn("ls");

Si cela échoue toujours, je ne pense pas que vous fassiez fonctionner Spawn du tout et je vous en suis reconnaissant. Au moins, l’Exec travaille.

Pas beaucoup dans le domaine des réponses pour vous, mais comme je l'ai dit, je ne vois rien de ce que vous faites mal.

De plus, je ne vois pas comment votre commande npm va fonctionner parce que vous ne spécifiez pas ce qu'il faut installer, mais cela dit, elle échoue d'une manière différente de celle que je vois, elle échoue ici si j'utilise la même commande . . . Je vois beaucoup de sorties stderr, pas une erreur globale.

BTW, je suis sous le noeud v0.8.21. Vous pouvez l'interroger par noeud -v. Si vous utilisez une autre version, essayez 0.8.21.

0
Brian