web-dev-qa-db-ja.com

出力をバッファリングせずにNode.jsからシェルコマンドを実行する

Node.jsからシェルコマンドを起動しようとしています。そのコマンドの入力と出力をリダイレクトせずに-シェルスクリプトまたはRubyのsystemコマンド。子プロセスがSTDOUTに書き込みたい場合、コンソールに直接行きます(または、Nodeアプリの出力がリダイレクトされた場合はリダイレクトされます)。

Nodeにはこれを行う簡単な方法はないようです。別のプロセスを実行する唯一の方法は_child_process_を使用することであるように見えます。これはalwaysが子プロセスの入力と出力をパイプにリダイレクトします。これらのパイプからデータを受け取り、それをプロセスのSTDOUTおよびSTDERRに書き込むコードを作成できますが、それを行うと、APIにより柔軟性が犠牲になります。

次の2つの機能が必要です。

  • シェル構文。コマンド間で出力をパイプするか、Windowsバッチファイルを実行できるようにします。
  • 無制限の出力。コンパイラーにシェルアウトして、メガバイトのコンパイラー警告を生成したい場合は、それらすべてを画面上でスクロールさせてください(ユーザーがうんざりしてCtrl + Cを押すまで)。

Nodeは、これら2つの機能のいずれかを強制的に選択させたいと考えています。

  • 無制限の量の出力が必要な場合は、 _child_process.spawn_ を使用してからchild.stdout.on('data', function(data) { process.stdout.write(data); });stderrに対して同じことを行うことができます。牛が帰宅するまでデータをパイプで送ってください。残念ながら、spawnはシェル構文をサポートしていません。
  • シェル構文が必要な場合は、 _child_process.exec_ を使用できます。しかし、execは、子プロセスのSTDOUTとSTDERRをバッファリングし、最後にそれらすべてを私に提供することを主張し、それらのバッファのサイズを制限します(デフォルトで200K)。生成された出力を表示したい場合は、on('data')イベントをフックできますが、execは引き続きバッファにデータを追加します。データ量が事前定義されたバッファサイズを超えると、execは子プロセスを終了します。

_child_process.execFile_ もあります。これは、柔軟性の観点から両方の世界のworstです。シェル構文はありませんが、上限を設定する必要があります。期待する出力)

何か不足していますか? ノード内の子プロセスにシェルアウトする方法はありますか?notはその入力と出力をリダイレクトしますか?シェルの構文をサポートし、シェルスクリプト、Rubyなどで利用できるように、事前に定義された量の出力の後に不要なものはありませんか?

52
Joe White

spawn引数を介してstdin/out/errorストリームを継承できるため、手動でパイプする必要はありません。

var spawn = require('child_process').spawn;
spawn('ls', [], { stdio: 'inherit' });

シェル構文にシェルを使用-bashの場合は-cパラメータは、文字列からスクリプトを読み取ります。

var spawn = require('child_process').spawn;
var shellSyntaxCommand = 'ls -l | grep test | wc -c';
spawn('sh', ['-c', shellSyntaxCommand], { stdio: 'inherit' });

要約すると:

var spawn = require('child_process').spawn;
function shspawn(command) {
   spawn('sh', ['-c', command], { stdio: 'inherit' });
} 

shspawn('ls -l | grep test | wc -c');
42
Andrey Sidorov

execspawnに置き換え、シェル構文を次のように単純に使用できます。

const {spawn} = require ('child_process');
const cmd = 'ls -l | grep test | wc -c';
const p = spawn (cmd, [], {Shell: true});

p.stdout.on ('data', (data) => {
  console.log (data.toString ());
});

魔法はただ{Shell: true}

6
Skywalker13

私はそれを使用していませんが、私はこのライブラリを見ました: https://github.com/polotek/procstreams

あなたはこれをするだろう。 .out()は、プロセスのstdin/outに自動的にパイプします。

var $p = require('procstreams');
$p('cat lines.txt').pipe('wc -l').out();

シェル構文をサポートしていない場合でも、それは非常に些細なことだと思います。

var command_str = "cat lines.txt | wc -l";
var cmds = command_str.split(/\s?\|\s?/);
var cmd = $p(cmds.shift());
while(cmds.length) cmd = cmd.pipe(cmds.shift());
cmd
  .out()
  .on('exit', function() {
    // Do whatever
  });
4
loganfsmyth

Child_processモジュールの node docs に例があります:

長時間実行プロセスを切り離し、その出力をファイルにリダイレクトする例:

 var fs = require('fs'),
     spawn = require('child_process').spawn,
     out = fs.openSync('./out.log', 'a'),
     err = fs.openSync('./out.log', 'a');

 var child = spawn('prg', [], {
   detached: true,
   stdio: [ 'ignore', out, err ]
 });

 child.unref();
0
darelf