Node.js v0.6.11 マニュアル & ドキュメンテーション


Child Processes #

Nodeは ChildProcess クラスを通じて 3 方向の popen(3) 機能を提供します。

それは完全にノンブロッキングな方法で子プロセスの stdinstdout、 そして stderr を通じたデータストリームを実現します。

子プロセスの生成は require('child_process').spawn() を使います。

子プロセスは常に 3 本のストリームと関連づけられています。 child.stdinchild.stdout、そして child.stderr です。

ChildProcessEventEmitter です。

Event: 'exit' #

function (code, signal) {}

このイベントは子プロセスが終了した後で生成されます。 プロセスが普通に終了した場合、code はプロセスの終了コードです。 それ以外の場合は null です。 プロセスがシグナルを受け取って終了した場合、signal は文字列によるシグナルの名前です。 それ以外の場合は null です。

waitpid(2) を参照してください。

child.stdin #

子プロセスの stdin を表現する Writable Stream です。 多くの場合、end() を通じてこのストリームを閉じると子プロセスが終了する原因となります。

child.stdout #

子プロセスの stdout を表現する Readable Stream です。

child.stderr #

子プロセスの stderr を表現する Readable Stream です。

child.pid #

子プロセスの PID です。

例:

var spawn = require('child_process').spawn,
    grep  = spawn('grep', ['ssh']);

console.log('Spawned child pid: ' + grep.pid);
grep.stdin.end();

child_process.spawn(command, [args], [options]) #

args をコマンドライン引数として、与えられた command で新しいプロセスを起動します。 args が省略された場合、空の配列がデフォルトとなります。

第 3 引数は追加のオプションを指定するために使われ、そのデフォルトは:

{ cwd: undefined,
  env: process.env,
  setsid: false
}

cwd で起動されたプロセスのワーキングディレクトリを指定することができます。 env は新しいプロセスに見える環境変数を指定するために使います。

setsid に true が設定されると、サブプロセスは新しいセッションで実行されます。

ls -lh /usr を実行して stdoutstderr、および終了コードを取得する例:

var util  = require('util'),
    spawn = require('child_process').spawn,
    ls    = spawn('ls', ['-lh', '/usr']);

ls.stdout.on('data', function (data) {
  console.log('stdout: ' + data);
});

ls.stderr.on('data', function (data) {
  console.log('stderr: ' + data);
});

ls.on('exit', function (code) {
  console.log('child process exited with code ' + code);
});

とても手の込んだ方法で実行する 'ps ax | grep ssh' の例:

var util  = require('util'),
    spawn = require('child_process').spawn,
    ps    = spawn('ps', ['ax']),
    grep  = spawn('grep', ['ssh']);

ps.stdout.on('data', function (data) {
  grep.stdin.write(data);
});

ps.stderr.on('data', function (data) {
  console.log('ps stderr: ' + data);
});

ps.on('exit', function (code) {
  if (code !== 0) {
    console.log('ps process exited with code ' + code);
  }
  grep.stdin.end();
});

grep.stdout.on('data', function (data) {
  console.log(data);
});

grep.stderr.on('data', function (data) {
  console.log('grep stderr: ' + data);
});

grep.on('exit', function (code) {
  if (code !== 0) {
    console.log('grep process exited with code ' + code);
  }
});

exec の失敗をチェックする例:

var spawn = require('child_process').spawn,
    child = spawn('bad_command');

child.stderr.setEncoding('utf8');
child.stderr.on('data', function (data) {
  if (/^execvp\(\)/.test(data)) {
    console.log('Failed to start child process.');
  }
});

spawn() は空の options オブジェクトを受け取ると、 process.env を使うのではなく,空の環境変数で子プロセスを起動します。 これは廃止された API との互換性のためです。

特定のファイル記述子を子プロセスの標準入出力に指定することを可能にする、 customFds と呼ばれる廃止されたオプションがありました。 この API は全てのプラットフォームに移植可能ではないために削除されました。 customFds は新しいプロセスの [stdin, stdout, stderr] を既存のストリームに接続することを可能にしました; -1 は新しいストリームが作られなければならないことを意味していました。 使用する場合は自己責任で。

よく似た内部的なオプションがあります。 具体的には stdinStreamstdoutStreamstderrStream です。 これらは 内部用途です。 Node のドキュメント化されていない API と同様に、 これらを使用すべきではありません。

関連項目: child_process.exec()

child_process.exec(command, [options], callback) #

コマンドをシェルで実行し、その出力をバッファに格納します。

var util = require('util'),
    exec = require('child_process').exec,
    child;

child = exec('cat *.js bad_file | wc -l',
  function (error, stdout, stderr) {
    console.log('stdout: ' + stdout);
    console.log('stderr: ' + stderr);
    if (error !== null) {
      console.log('exec error: ' + error);
    }
});

コールバックは引数 (error, stdout, stderr) を得ます。 成功すると、errornull になります。 エラーだと、errorError のインスタンスとなり、 err.code は子プロセスの終了コード、 err.signal はプロセスを終了させたシグナルとなります。

任意の第 2 引数でいくつかのオプションを指定することができます。 オプションのデフォルトは

{ encoding: 'utf8',
  timeout: 0,
  maxBuffer: 200*1024,
  killSignal: 'SIGTERM',
  cwd: null,
  env: null }

もし timeout が 0 より大きいと、 子プロセスは実行時間が timeout ミリ秒よりも長くなると kill されます。 子プロセスは killSignal で kill されます (デフォルト: 'SIGTERM')。 maxBuffer は標準出力と標準エラーの最大のデータ量を指定します - この値を超えると子プロセスは kill されます。

child_process.execFile(file, args, options, callback) #

子シェルで実行する代わりに指定されたファイルを直接実行することを除いて child_process.exec() と同様です。 これは child_process.exec より若干効率的で、同じオプションを持ちます。

child_process.fork(modulePath, arguments, options) #

これは spawn() の特別版で、Node プロセスを起動します。 返されるオブジェクトは通常の ChildProcess の全てのメソッドに加えて、 組み込みの通信チャネルを持ちます。 チャネルは child.send(message, [sendHandle]) によって書き込まれ、 メッセージを受信すると child 上で 'message' イベントが生成されます。

例:

var cp = require('child_process');

var n = cp.fork(__dirname + '/sub.js');

n.on('message', function(m) {
  console.log('PARENT got message:', m);
});

n.send({ hello: 'world' });

そして子スクリプトの 'sub.js' は次のようになります:

process.on('message', function(m) {
  console.log('CHILD got message:', m);
});

process.send({ foo: 'bar' });

子供の process オブジェクトは send() メソッドを持ち、 process はチャネルでメッセージを受信するたびにイベントを生成します。

デフォルトでは、起動された Node プロセスは親プロセスに関連づけられた標準入力、 標準出力、標準エラー出力を持ちます。

これらの子 Node は、やはり V8 の新しいインスタンスです。 新しい Node ごとに少なくとも 30 ミリ秒の起動時間と 10MB のメモリを前提としてください。 つまり、数千の子プロセスを作ることは出来ません。

child.send()sendHandle オプションはハンドルオブジェクトを別プロセスに 送ります。 子プロセスはそのハンドルを message イベントの第2引数として受け取ります。 これはハンドルを送信するサンプルです。

var server = require('net').createServer();
var child = require('child_process').fork(__dirname + '/child.js');
// Open up the server object and send the handle.
server.listen(1337, function() {
  child.send({ server: true }, server._handle);
});

これはサーバのハンドルを受信してプロセス間で共有するサンプルです。

process.on('message', function(m, serverHandle) {
  if (serverHandle) {
    var server = require('net').createServer();
    server.listen(serverHandle);
  }
});

child.kill([signal]) #

子プロセスにシグナルを送ります。 引数が与えられない場合、子プロセスには 'SIGTERM' が送られます。 利用可能なシグナルの一覧は signal(7) を参照してください。

var spawn = require('child_process').spawn,
    grep  = spawn('grep', ['ssh']);

grep.on('exit', function (code, signal) {
  console.log('child process terminated due to receipt of signal '+signal);
});

// send SIGHUP to process
grep.kill('SIGHUP');

この関数は kill と呼ばれるものの、 子プロセスに届けられるシグナルが実際には子プロセスを殺さないかもしれないことに注意してください。 kill はただプロセスにシグナルを送るだけです。

See kill(2)