昨日node の spawn に関して調べてみた のエントリで、昨日のエントリで終えることができなかったことがある。それは、exec と、spawn の違いの検証だ。
昨日は、パイプ処理を含むspawn を実行してみようとしたが、何も出力されなかったのが理由がわかった。下記のように、サンプルコードの、Readble の on の第一引数がとる値が間違えていた。Class: stream.Readableに指定できる値下記の通り
- Event 'close' ストーリむがクローズされたとき
- Event 'data' データのチャンクのオーナが破棄されたとき。チャンクが到着したイメージ。よく理解できていないがヤクの毛がりにならないよう、次回のテーマとしたい。
- Event 'end' ストリームのデータが終わった時
- Event 'error' ストリームが何らかの問題のため、データを生成できなくなったとき
- Event 'readable' ストリームからデータが読み出し可能になったとき。
import * as child_process from "child_process";
namespace Spawnspike {
let proc = child_process.spawn('ls', ['-l', '|', 'grep', 'exec']);
proc.stderr.on('data', (err) => { // 昨日は、data 部分が error だった
console.error(err.toString());
console.log('spawn Error *********');
})
proc.stdout.on('data', (data) => {
console.log(data.toString());
console.log('spawn Success!');
})
}
つまり、error
はストリームがらみで問題が発生したケースのEvent なので、ここでは、errorのストリームの on を普通に読むためには data
を指定する必要がある。
spawn と exec
リファレンスを見ていると、spawn も、exec のように、シェル実行が出来ることに気が付いた。3つ目のオプションを指定すればいい。違いを見てみよう。
上記のプログラムを実行。予想通り、パイプが処理できない。
$ node spawnspike.js
ls: '|' にアクセスできません
spawn Error *********
: そのようなファイルやディレクトリはありません
ls: 'grep' にアクセスできません: そのようなファイルやディレクトリはありません
ls: 'exec' にアクセスできません: そのようなファイルやディレクトリはありません
spawn Error *********
shell のオプションを指定
import * as child_process from "child_process";
namespace Spawnspike {
let proc = child_process.spawn('ls', ['-l', '|', 'grep', 'exec'], { shell: true});
proc.stderr.on('data', (err) => {
console.error(err.toString());
console.log('spawn Error *********');
})
proc.stdout.on('data', (data) => {
console.log(data.toString());
console.log('spawn Success!');
})
}
結果
$ node spawnspike.js
-rwxrwxrwx 1 root root 896 7月 17 04:04 exec.js
-rwxrwxrwx 1 root root 777 7月 16 17:13 exec.ts
-rwxrwxrwx 1 root root 635 7月 17 04:04 execfile.js
-rwxrwxrwx 1 root root 507 7月 16 16:58 execfile.ts
spawn Success!
実行に成功した。
では、spawn と exec の違いは?
となると、spawn と exec の違いは?となるのだが、シェルが実行できるのは両方できるが、exec がバッファの終了まで待つのに対して、spawn はストリームだ。execFile は、シェルが実行できなくて、バッファ終了まで待つタイプ。
うん。すっきりした。