web-dev-qa-db-ja.com

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'
  }
}

どこでもエラーをスローすることなく、execを使用して正常に機能した同じコマンドをspawnに実行させるにはどうすればよいですか?そして、なぜこれが機能しないのですか? APIを読む http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options は、これがまさにspawnの使用方法を示唆しているようです...

さまざまなことを何度も試した後、最終的に「npm」が実際にウィンドウ上にあるものを見て、npmというbashスクリプトと、npm.cmdというwindowsネイティブバッチスクリプトであることがわかりました。 (なぜそれが.cmdなのかわかりません。これは.batですが、そこにあります)。 Windowsのコマンドリゾルバーはnpmを参照し、実行可能ファイルではないことに気づき、npm.cmdを参照してから、IS実行可能ファイルに気づき、代わりにそれを使用します。これは、ターミナルにいるときに役立ちますが、spawn()はそのような解決を行いません。それを渡すと、npmは実行可能ファイルではないため失敗します。ただし、npm.cmdをコマンドとして渡すと問題なく動作します。

(また、rmが以前に失敗した理由もわかりません。なぜなら、それは、私が知ることができる変更なしで実際に正しく動作するからです。

そのため、WindowsでspawnとENOENTを実行した場合、トリガーしようとしているコマンドがプレーンなコマンドプロンプトで機能する場合、呼び出しているコマンドが真の実行可能ファイルであるかどうか、または代わりにコマンドプロンプトが「役立つ」ように実行する.bat/.cmdファイル。もしそうなら、それを生成します。

編集

この投稿はまだ賛成票を集めているので、コマンドが常に機能するようにする良い方法は、process.platformに基づいてbootstrapすることです。これはWindowsではwin32になります。

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

これはある種のcygwinの落とし穴だと思う。私はUbuntu 12.04を実行していますが、問題を再現しようとしましたが、私にとっては問題なく動作します。要するに、私はあなたが間違っていることは何も見ていません。

オプションについて不満がある場合は、次のように複数のオプションに分割することをお勧めします。

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

これは一種のひょうきんですが、私のUbuntu 12.04でも同様に機能します。単一のファイルを削除して、同じ結果が得られるかどうかを確認してみてください。

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

それでも失敗する場合は、おかしなことに対処していることがわかります。

次のようなパラメーターを指定せずにコマンドを実行することもできます。

child = spawn("ls");

それでも失敗する場合は、spawnが動作する可能性がまったくない可能性があり、少なくともexecが動作していることに感謝します。

あなたの答えの領域にはあまりありませんが、私が言ったように、あなたが間違っていることは何もわかりません。

さらに、インストールするものを指定していないため、npmコマンドがどのように動作するのかわかりませんが、同じコマンドを使用するとここで失敗するのとは異なる方法で失敗します。 。 。全体的なエラーではなく、多くのstderr出力が表示されます。

ところで、私はノードv0.8.21を実行しています。ノード-vでクエリできます。別のバージョンを実行している場合は、0.8.21を試してみてください。

0
Brian