Использование nodejs spawn вызывает ошибки "unknown option -" и "[Error: spawn ENOENT]"

Я пытаюсь получить spawn для выполнения rm -rf node_modules, за которым следует npm install (в Windows 7; команды nx предоставлены прозрачно установленным CygWin. Все команды nx разрешают на командной строке просто отлично).

Я изначально использовал это с помощью exec, но хотел поймать информацию stdout/stderr по мере ее возникновения, поэтому я решил использовать spawn и переписать код для его использования. Однако это все ломает.

Команда rm, переписанная, стала следующей:

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

Однако при запуске это приводит к следующей ошибке:

rm: unknown option -- ,

Try `rm --help' for more information.

Команда npm, переписанная, стала следующей:

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

Однако при запуске это приводит к следующей ошибке:

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

Как заставить spwn запускать те же команды, которые отлично работали с помощью exec, не вызывая ошибок во всем месте? И почему это не работает? Чтение API, http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options, похоже, предполагает, что именно так предполагается использовать икру...

Ответ 1

После долгих попыток по-разному я наконец-то взглянул на то, что на самом деле означает "npm" в Windows, и оказалось, что это bash-скрипт с именем npm, а также пакетный скрипт для npm.cmd называемый npm.cmd (понятия не имею) почему это .cmd, это должно быть .bat, но там у вас есть). Средство распознавания команд Windows увидит npm, заметит, что это не исполняемый файл, увидит npm.cmd, а затем заметит, что это исполняемый файл, и затем будет использовать его вместо этого. Это полезно, когда вы находитесь в терминале, но spawn() не будет делать такого разрешения: передача его через npm приведет к сбою, потому что это не исполняемый файл. Передача в качестве команды npm.cmd, однако, работает отлично.

(Кроме того, не уверен, почему ранее rm неудачу, так как это на самом деле работает правильно, без каких-либо изменений, которые я могу сказать. Возможно, неправильно воспринял это как часть проблемы, хотя на самом деле это не так.)

Итак: если вы запускаете spawn надписью ENOENT в окнах, когда команда, которую вы пытаетесь вызвать, работает в простой командной строке, выясните, является ли команда, которую вы вызываете, истинным исполняемым файлом или существует .bat/.cmd файл, который вместо вас будет запускать командная строка. Если это так, порождайте это.

редактировать

так как в этом посте по-прежнему поступают ответы, хороший способ убедиться, что команда всегда работает, - это загрузить ее на основе process.platform, который будет win32 для windows.

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

Ответ 2

Я думаю, что это может быть какой-то cygwin gotcha. Я запускаю Ubuntu 12.04 и пытался дублировать вашу проблему, но для меня это работает отлично. Короче говоря, я не вижу ничего, что вы делаете неправильно.

Если он жалуется на этот вариант, возможно, разбить его на несколько вариантов:

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

Такой градиент, но это работает и на моем Ubuntu 12.04. Вы можете попытаться просто удалить один файл и посмотреть, получаете ли вы то же самое.

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

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

Вы даже можете попытаться просто выполнить команду без таких параметров:

child = spawn("ls");

Если это все еще не удастся, вы вряд ли получите, что икру будет работать вообще, я буду догадываться и буду благодарен, что работает хотя бы exec.

Не так много в области ответов для вас, но, как я уже сказал, я не вижу ничего, что вы делаете неправильно.

Кроме того, я не вижу, как ваша команда npm будет работать, потому что вы не указали, что устанавливать, но, как говорится, она терпит неудачу иначе, чем я вижу, что она не работает здесь, если я использую та же команда., Я вижу много выходных данных stderr, а не общую ошибку.

Кстати, я запускаю node v0.8.21. Вы можете запросить это с помощью node -v. Если вы используете другую версию, возможно, попробуйте выполнить 0.8.21.

Ответ 3

Используйте полный путь для процесса, например:

var cmd = require('child_process').spawn("C:\\windows\\system32\\cmd.exe");