nodejs: child_process.spawn とシェル実行の方法の模範解答についてのメモ(あるいはバッドノウハウを広めないための自分用の戒めとしてのメモというかあけおめ生存報告のメモ)
最初に答え
let spawn = require('child_process').spawn; // 模範解答(たぶん) let p = spawn( 'echo', [ 'hoge' ], { 'shell': true } ); p.stdout.on( 'data', payload => console.log( `[spawn/stdout]: ${payload.toString().trim()}` ) ) p.stderr.on( 'data', payload => console.log( `[spawn/stderr]: ${payload.toString().trim()}` ) ) p.on( 'exit', exit_code => console.log( `[spawn/exit] ${exit_code}` ) )
参考
要点
spawn
には第3仮引数のoptions
というのがありますoptions
のshell
を定義すると、
例えば、 powershell
をシェルとして実行したい場合は↓のようになります。
let spawn = require('child_process').spawn; let p = spawn( 'Get-ChildItem', [ '..' ], { 'shell': 'powershell' } ); p.stdout.on( 'data', payload => console.log( `[spawn/stdout]: ${payload.toString().trim()}` ) ) p.stderr.on( 'data', payload => console.log( `[spawn/stderr]: ${payload.toString().trim()}` ) ) p.on( 'exit', exit_code => console.log( `[spawn/exit] ${exit_code}` ) )
powershell
は通常は Windows 環境のシステム標準で PATH が通り、 PATHEXT に .EXE があり NTFS は case-insensitive なので、実行ファイルのフルパスを書かなくても powershell
だけで実行でき、かつ -c
オプションが期待動作するのでこれで使えます。
おまけ
諸事情により7年ぶりに TypeScript でおもちゃを書きはじめました。それで、なんでわざわざこんなメモを残したのかというと、世の中にはしばしば公式ドキュメントを読めばきれいな実現方法が書いてあるのに、読まずに、"俺は試行錯誤の結果こうしたらできたからみんなもこうするといいよ"的な野良バッドノウハウがおそらく誰も悪意などなく意図せずとも広まりやすい言語というのがあります。それ自体は発生してしまったものですし、わざわざあちこちに公開されているバッドノウハウへたまたま見つけたからというだけで7年ぶりにちょっと触った程度の nodejs 初心者がマサカリを投げるほど、私は傲慢でも暇でも親切でもないのですが、自分用には面白い戒めにもなるな、と思い、少し丁寧にメモを残してみました。
// これは日本語に限らず、参考用にソースを眺めたOSSでも少なくなかったバッドノウハウの例です let p = spawn( 'cmd', [ '/c', 'echo', 'this is a bad know-how; read the official document first.' ] )
私もたくさんのバッドノウハウを悪意はなくとも広めてしまっている事もあるのでしょうが、なかのひとの気持ちとしてはできるだけきれいに、かつ(複数の意味で)面倒なく快適に、これからもお鮨を食べ、フリッツを食べ、不幸よりも幸せを多く感じて2020年以降も生きたいと思います。
あけおめ。