Node.jsでシェルコマンドを実行させる方法はいくつか存在します。ここでは、「exec」「execSync」「spawn」について動作の違いを確認します。
目次
exec
(非ストリーム形式, 非同期実行)
exec の動作確認をします。exec.js というファイルに以下処理を記述します。
const { exec } = require('child_process')
exec('ls -l sample.txt', (err, stdout, stderr) => {
if (err) {
console.log(`stderr: ${stderr}`)
return
}
console.log(`stdout: ${stdout}`)
}
)
console.log('わくわくBank')コールバックでコマンドの出力結果を取得できます。
$ node exec.js
わくわくBank
stdout: -rwxr-xr-x 1 xxx xxx 21166 Nov 22 01:02 sample.txt非同期なので わくわくBank の出力が先に行われています。
ls の部分を存在しないコマンド( aaa )にしてエラーを発生させてみます。
$ node exec.js
わくわくBank
stderr: /bin/sh: aaa: command not foundexecSync
(非ストリーム形式, 同期実行)
同期実行させたい場合、execSync を利用します。
execSync の動作確認をします。execSync.js というファイルに以下処理を記述します。
const { execSync } = require('child_process')
const stdout = execSync('ls -l sample.txt')
console.log(`stdout: ${stdout.toString()}`)
console.log('わくわくBank')$ node execSync.js
stdout: -rwxr-xr-x 1 xxx xxx 21166 Nov 22 01:02 sample.txt
わくわくBankspawn
(ストリーム形式, 非同期実行)
大きいデータを扱う場合、ストリーム形式である spawn のほうが適しています。
(一度に全てのデータをメモリに読み込むとメモリ不足になるため)
spawn の動作確認をします。spawn.js というファイルに以下処理を記述します。
const { spawn } = require('child_process')
const childProcess = spawn('cat', ['sample.txt'])
console.log('process id:' + process.pid)
console.log('child process id:' + childProcess.pid)
childProcess.stdout.on('data', (chunk) => {
console.log(new Date())
console.log(chunk.length)
// console.log(chunk.toString())
})$ node spawn.js
process id:44066
child process id:44093
2019-11-21T16:32:48.073Z
8192
2019-11-21T16:32:48.076Z
8192
2019-11-21T16:32:48.076Z
4782spawn の場合、上記のように少しずつデータを取得しています。
比較として execSync の動作確認を行います。
const { execSync } = require('child_process')
const stdout = execSync('cat sample.txt')
console.log(`stdout: ${stdout.length}`)execSync の場合、以下のように一括でデータを取得しています。
$ node execSync.js
stdout: 21166