command の 標準入出力 覚書

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

command を 新規のプロセスで実行し、subprocess を生成する。 (command は 子プロセスとなる)

options.stdio

command の標準入出力先を設定する。

  • pipe: デフォルト。commandの標準入出力は、subprocess.stdio とつながる
  • inherit: commandの標準入出力は、process.stdio が引き継がれる
  • ignore: /dev/null
  • <Stream>: ファイルへのリダイレクト

pipe

command の 入出力が、 subprocess.stdio とつながる。

ps ax | grep ssh の実現コード

const { spawn } = require('child_process');

// ps が subprocess 
const ps = spawn('ps', ['ax']);

// grep が subprocess
const grep = spawn('grep', ['ssh']);

// subprocess.stdout を使って command の標準出力結果を受け取る
ps.stdout.on('data', (data) => {
  grep.stdin.write(data);
});

// subprocess.stdout を使って command の標準エラー結果を受け取る
ps.stderr.on('data', (data) => {
  console.error(`ps stderr: ${data}`);
});

// command の exit は subprocess を 使ってハンドリングできる
ps.on('close', (code) => {
  if (code !== 0) {
    console.log(`ps process exited with code ${code}`);
  }
  grep.stdin.end();
});

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

サブプロセスがNode.jsツールの場合

process.stdiosubprocess.stdio につながる

親プロセス (pipe.js)

const { spawn } = require('child_process')

// subprocessの生成
const subprocess = spawn('./subcommand.js', ['hello']) 
subprocess.stdout.on('data', (data) => {
    console.log('subcommand answered: ')
    console.log(data.toString('utf-8'))
})

子プロセス (subcommand.js)

#!/usr/bin/env node

const args = process.argv.slice(2)

// 親のsubprocess.stdoutに書き込まれる
process.stdout.write(`You inputed: ${args}\n`)
process.stdout.end('over')

実行

$ node pipe.js 
subcommand answered: 
You inputed: hello
over

inherit

command の入出力が process.stdio (標準入出力(0, 1, 2)) とそのままつながる。 subprocess.stdout, subprocess.stderr へのアクセスはクラッシュする。

vimの起動。(vimの標準入出力にsubprocess.stdioを割り当てるとvimが起動できない)

const { spawn } = require('child_process');

const subprocess = spawn(
  'sh',
  [
    '-c',
    'vim'
  ], {
      stdio: ['inherit', 'inherit', 'inherit']
  }
);
  • sh -c: 最初の引数を command として実行する

覚書

登場人物

  • 自身のスクリプト = 親プロセス
  • command = 子プロセス
  • subprocess = child_process.spawn(command[, args][, options]) メソッドで生成されるインスタンス。 commandとのやり取りに使う。

プロセスのdetachも可能

options.detached を trueにすることで、親プロセスから独立して子プロセスを実行する。

プロセス通信も可能

IPCチャンネルを通してcommandとのプロセス通信が可能。 (subprocessを通して行う。エレガントやんか。)

参照

class ChildProcess

nodejs.org

subprocessは、ChildProcessのサブクラスのインスタンス

標準入出力(stdio) について

www.cas.cmc.osaka-u.ac.jp