child_process.execではなく、child_process.spawnを使うと実現できます。
exec ... プログラムの終了を待つため、出力をリアルタイムに扱えない。
spawn ... プログラムの終了を待たない。非同期に実行。
例)
#!/usr/bin/env node
// プログラムの出力を扱う場合はexecではなく、spawnを利用
const { spawn, /*exec*/ } = require('child_process');
(async () => {
// プログラム名
const program = 'tshark';
// プログラムの引数
const args = ['-i', 'wlp2s0', '-Y', 'http', '-x'];
// プログラムを起動。プログラムの終了を待たずに戻ってくる
const child = spawn(program, args, {
// spawnのstdioオプション
// [標準入力, 標準出力, 標準エラー出力] の形式で指定
// 'ignore' -> nulや/dev/null相当
// 'pipe' -> nodeプログラムで扱う場合はこれを指定
// 'inherit' -> このnodeプロセスのものをそのまま使う
// そのほか ドキュメント参照 https://nodejs.org/api/child_process.html#child_process_options_stdio
stdio: ['ignore', 'pipe', 'inherit'],
});
// 標準出力が出力される毎にループを回す
for await (const chunk of child.stdout) {
// chunkは標準出力が出力するデータのまとまり
// 行単位でもなんでもなく、バッファがいっぱいになるか、
// 出力が一段落したかなど、人としては予測ができない塊
console.log("*****");
console.log(String(chunk));
console.log("#####");
}
})().catch(console.error);
※プログラムの引数は適宜置き換えて下さい。
ただ、これではコメントにも記載していますが、出力を扱えるタイミングが予想できないです。
readlineを使うと行単位の出力を扱えます。
#!/usr/bin/env node
// プログラムの出力を扱う場合はexecではなく、spawnを利用
const { spawn, /*exec*/ } = require('child_process');
// 追加
const readline = require('readline');
(async () => {
// プログラム名
const program = 'tshark';
// プログラムの引数
const args = ['-i', 'wlp2s0', '-Y', 'http', '-x'];
// プログラムを起動。プログラムの終了を待たずに戻ってくる
const child = spawn(program, args, {
// spawnのstdioオプション
// [標準入力, 標準出力, 標準エラー出力] の形式で指定
// 'ignore' -> nulや/dev/null相当
// 'pipe' -> nodeプログラムで扱う場合はこれを指定
// 'inherit' -> このnodeプロセスのものをそのまま使う
// そのほか ドキュメント参照 https://nodejs.org/api/child_process.html#child_process_options_stdio
stdio: ['ignore', 'pipe', 'inherit'],
});
const lines = readline.createInterface({ input: child.stdout });
// 標準出力の行単位でループを回す
for await (const line of lines) {
console.log("*****", line, "#####");
}
})().catch(console.error);
なお、tsharkのオプションで-T ek
を指定すると通信が行単位でJSONとして出力されるので、より扱いやすそうでした。
なお、プログラムを非同期で扱うことになるので、同期での実行に比べエラー処理等の難易度が上がります。頑張って下さい!
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。