12. SubProcess
subprocessオブジェクトは、パイプを使用した外部アプリケーション間プロセス通信機能を提供する組み込みオブジェクトです。
機能概要:
- 外部アプリケーションの標準入力(stdin)、標準出力(stdout)、標準エラー出力(stderr)をそれぞれパイプ接続し、リアルタイムでデータを送受信する機能を提供します。
- 外部アプリケーションに特定シグナルを送信する機能を提供します。
- 外部アプリケーションの終了コードを取得する機能を提供します。
制限事項:
- 使用可能なコマンド実行リソースは
5
本です。(Version 00.00.03+) (旧バージョン:3
)
subprocess Global Object
Methods()/Properties | Summary | Version | Note |
---|---|---|---|
subprocess.create() | コマンド実行インスタンスを生成します。 |
subprocess.create(cmd[,options])
コマンド実行インスタンスを生成します。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
cmd | string, Array | mandatory | コマンド実行パスを文字列で指定します。コマンド引数が必要な場合はコマンド実行パスの後に空白文字区切りで指定します。空白文字を含む文字列を1つの引数として扱う場合は、対象となる文字列範囲をシングルクォート' またはダブルクォート" で囲んでください。尚、コマンド文字数は最大4095 バイト、コマンド実行パスを含めたコマンド引数は最大32 までとなります。コマンド実行パスを文字列の配列で指定します。コマンド引数が必要な場合はコマンド実行パス後の要素に追加指定します。尚、配列長は最大 32 まで、また要素毎の文字列長にそれぞれ1を加算した合計サイズが4096 バイト以内に収まる必要があります。 | リダイレクト、パイプを使用した複数コマンドの組み合わせによる実行はサポートしていません。 ( Array 対応: Version 00.00.03+) |
options | Object | optional | オプション 詳細はOptionsを参照してください。 | |
return | {Exec}, null | - | {Exec} : 生成された{Exec} null : リソース不足でインスタンスの生成が失敗した場合 | パラメータ異常の場合は例外となります。 |
Options
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
readBuffSize | number | optional | 読み出しバッファサイズ[Byte] 設定範囲: 1~2,147,483,647 デフォルト値は4096となります。 | |
abortSigNo | number | optional | 強制終了シグナル番号 .abort()メソッドコール等により、強制的にコマンド実行プロセスを中止させる際に送信するシグナル番号を指定します。実行プロセスはこのシグナル番号で必ず終了可能である必要があります。 設定範囲: 1 (SIGHUP), 2 (SIGINT),9 (SIGKILL), 15 (SIGTERM)デフォルト値は 15 (SIGTERM)となります。 |
下記は使用例となります。
シンプルなコマンドを取り扱う場合は文字列指定、コマンド引数にシングルクォート'
またはダブルクォート"
が含まれる場合や複雑なコマンドを扱う場合は、配列指定が有効です。
var exec = subprocess.create('date');
var exec = subprocess.create("uname -a");
var exec = subprocess.create("ls -l /tmp");
var exec = subprocess.create("cat /tmp/memo.txt");
var exec = subprocess.create("tail -f /tmp/memo.txt");
var exec = subprocess.create('/usr/bin/myApp "hello world"');
var exec = subprocess.create('/home/user/start.sh "abc" 1 2 3');
var exec = subprocess.create(['date']);
var exec = subprocess.create(['uname', '-a']);
var exec = subprocess.create(['ls', '-l', "/tmp"]);
var exec = subprocess.create(['cat', "/tmp/memo.txt"]);
var exec = subprocess.create(['tail', '-f', "/tmp/memo.txt"]);
var exec = subprocess.create(['/usr/bin/myApp', "hello world"]);
var exec = subprocess.create(['/home/user/start.sh', "abc", '1', '2', '3']);
var exec = subprocess.create(['bash', '-c', 'echo "hello world"']);
var exec = subprocess.create(['bash', '-c', "echo \"hello world\""]);
var exec = subprocess.create(['bash', '-c', "grep processor /proc/cpuinfo | wc -l"]);
{Exec}
Methods()/Properties | Summary | Version | Note |
---|---|---|---|
.on() | イベントハンドラを登録します。 | ||
.execute() | コマンド実行を開始します。 | ||
.read() | コマンド実行プロセスから受信した標準出力(stdout)データを読み出します。 | ||
.readError() | コマンド実行プロセスから受信した標準エラー出力(stderr)データを読み出します。 | ||
.write() | コマンド実行プロセスの標準入力(stdin)にデータを送信します。 | ||
.sendSignal() | コマンド実行プロセスに指定されたシグナルを送信します。 | ||
.isBusy() | コマンド実行プロセスの実行状態を取得します。 | ||
.getResult() | コマンド実行プロセスの終了コードを取得します。 | ||
.abort() | コマンド実行プロセスを強制的に中止します。 | ||
.release() | コマンド実行リソースを解放します。 |
Details
.on(event,callback)
イベントハンドラを登録します。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
event | string | mandatory | イベント名 使用できるイベント名は、stdout, stderr, exitとなります。 | |
callback | function | mandatory | イベント発生時にコールバック処理を実行します。 | |
return | undefined | - | - | パラメータ異常の場合は例外となります。 |
event : ’stdout’
コマンド実行プロセスから標準出力(stdout)データを受信し、読み出しバッファにデータが格納された際にコールバック処理を実行します。
event : ’stderr’
コマンド実行プロセスから標準エラー出力(stderr)データを受信し、読み出しバッファにデータが格納された際にコールバック処理を実行します。
event : ’exit’
コマンド実行プロセスが終了した際にコールバック処理を実行します。
尚、標準出力(stdout)および標準エラー出力(stderr)の読み出しバッファにデータが存在する状態でプロセスが終了した場合、コールバック処理はすぐに実行されません。必ず.read()または.readError()メソッドで全てのデータを読み出す必要があります。
.execute()
コマンド実行を開始します。
スーパーユーザー(root
)権限でコマンド実行されます。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
return | boolean | - | true: 成功 false: 失敗 |
.read([isBin])
コマンド実行プロセスから受信した標準出力(stdout)データを読み出します。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
isBin | boolean | optional | 読み出しデータの形式を指定します。 true: バイナリデータ形式で読み出し false: 文字列形式で読み出し デフォルト値はfalseとなります。 | |
return | ArrayBuffer, string | - | 読み出しデータ 戻り値の型はisBinで決定されます。 trueを指定した場合はArrayBuffer型、falseを指定した場合は、string型となります。 | 読み出しデータはreadBuffSizeで指定したサイズ以下となります。読み出しデータがない場合はサイズが0となります。 パラメータ異常の場合は例外となります。 |
.readError([isBin])
コマンド実行プロセスから受信した標準エラー出力(stderr)データを読み出します。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
isBin | boolean | optional | 読み出しデータの形式を指定します。 true: バイナリデータ形式で読み出し false: 文字列形式で読み出し デフォルト値はfalseとなります。 | |
return | ArrayBuffer, string | - | 読み出しデータ 戻り値の型はisBinで決定されます。 trueを指定した場合はArrayBuffer型、falseを指定した場合は、string型となります。 | 読み出しデータはreadBuffSizeで指定したサイズ以下となります。読み出しデータがない場合はサイズが0となります。 パラメータ異常の場合は例外となります。 |
.write(data)
コマンド実行プロセスの標準入力(stdin)にデータを送信します。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
data | string, ArrayBuffer | mandatory | 送信データ | |
return | number | - | 送信されたデータサイズ 送信が失敗した場合は-1を返却します。 | パラメータ異常の場合は例外となります。 |
.sendSignal(sigNo)
コマンド実行プロセスに指定されたシグナルを送信します。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
sigNo | number | mandatory | シグナル番号 設定範囲: 1~31 | |
return | boolean | - | true: 成功 false: 失敗 | パラメータ異常の場合は例外となります。 |
.isBusy()
コマンド実行プロセスの実行状態を取得します。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
return | boolean | - | 実行状態 true: 実行中 false: 終了または停止状態 |
.getResult()
コマンド実行プロセスの終了コードを取得します。
このメソッドはコマンド実行プロセスが終了した後に使用します。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
return | {ExecStatus} | - | {ExecStatus} : 終了コード |
{ExecStatus}
終了コードおよび終了シグナル番号は基本排他的であり、どちらか一方が無効値-1
となります。
尚、コマンド未実行またはコマンド実行中の場合は、全てのプロパティ値が-1
となります。
Name | Type | Summary | Note |
---|---|---|---|
.exitCode | number | コマンド実行プロセスの終了コード (0~255) コマンド実行プロセスが正常終了した場合に終了コードが設定されます。 | |
.sigNo | number | コマンド実行プロセスの終了シグナル番号 コマンド実行プロセスがシグナルにより終了した場合に終了の要因となったシグナル番号が設定されます。 | |
.wstatus | number | 終了ステータス情報 (参考データ) 終了コードおよび終了シグナル情報が格納されているオリジナルデータとなります。 |
.abort()
コマンド実行プロセスを強制的に中止します。
コマンド実行中の場合のみ有効となります。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
return | undefined | - | - |
.release()
コマンド実行リソースを解放します。
実行中のコマンドは強制終了となります。
Name | Type | M/O | Summary | Note |
---|---|---|---|---|
return | undefined | - | - |
オブジェクトの使用例
Sample 1
コマンドを実行するサンプルです。
uname -a
コマンドを実行し、システム情報を表示します。
var exec = subprocess.create("uname -a");
exec.execute();
while(1) {
var resp = exec.read();
if(resp.length) {
print('response : ' + resp);
}
if(!exec.isBusy()) {
break;
}
}
exec.release();
exec = undefined;
print('done');
Sample 2
.on()イベントコールバックを使用して、コマンドを実行するサンプルです。
uname -a
コマンドを実行し、システム情報を表示します。
var done = false;
var exec = subprocess.create("uname -a");
exec.on('stdout', function() {
var resp = exec.read();
print('response : ' + resp);
});
exec.on('exit', function() {
done = true;
});
exec.execute();
while(1) {
if(done) {
break;
}
}
exec.release();
exec = undefined;
print('done');
Sample 3
bashコマンド経由で、neqto.js上からシェルコマンドを直接実行するサンプルです。
コマンド実行リソースを維持したまま定期的にコマンドを実行し、/tmp
領域のディスク使用量を表示します。
var timerInterval = 1000; //ms
var maxNumOfTimes = 20;
var shellCmd = "df -h /tmp | sed '1d' | awk '{print $5}'";
//var exec = subprocess.create('bash -c "' + shellCmd + '"');
var exec = subprocess.create(['bash', '-c', shellCmd]);
var resp = false;
var done = false;
exec.on('stdout', function() { resp = true; });
exec.on('exit', function() { done = true; });
var trigger = false;
var tm = setInterval(function() {
if(trigger) print('overwritten');
trigger = true;
}, timerInterval);
var cnt = 0;
var state = 0;
while(1) {
if(state == 0) {
if(trigger) {
exec.execute();
cnt++;
state++;
}
} else if(state == 1) {
if(resp) {
var result = exec.read();
print(cnt, result.replace(/\n/g, ''));
state++;
}
} else if(state == 2) {
if(done) {
trigger = false;
resp = false;
state = 0;
if(cnt >= maxNumOfTimes) break;
}
}
}
clearInterval(tm);
exec.release();
exec = undefined;
print('script done');
Sample 4
外部に配置されているシェルスクリプトファイルを実行するサンプルです。
下記、テストシェルスクリプト「test.sh」を起動し、シェルスクリプトから受信した標準出力および標準エラー出力を表示します。又、一定時間経過後、標準入力を介して"end"
を送信し、シェルスクリプトを終了します。
本スクリプトを実行する前に「test.sh」を/tmp
下に配置し、実行権限を付加しておく必要があります。
test.sh
#!/bin/bash
CNT=0
while true; do
read -t 1 ENTER
if [ -n "$ENTER" ]; then
echo "$ENTER"
break
fi
if [ $((${CNT} % 2)) = 1 ]; then
echo "$CNT" 1>&2
else
echo "$CNT"
fi
CNT=$((CNT+1))
done
neqto.js
var delay = 10000; //ms
var done = false;
var exec = subprocess.create('/tmp/test.sh');
if(!exec) { throw new Error('Subprocess is out of resource'); }
exec.on('stdout', function() {
var str = exec.read();
print('stdout : ' + str.replace(/\n/g, ''));
});
exec.on('stderr', function() {
var str = exec.readError();
print('stderr : ' + str.replace(/\n/g, ''));
});
exec.on('exit', function() {
done = true;
});
exec.execute();
var tm = setTimeout(function() {
exec.write('end\n');
}, delay);
while(1) {
if(done) {
var res = exec.getResult();
print('.exitCode : ' + res.exitCode)
print('.sigNo : ' + res.sigNo)
break;
}
}
clearTimeout(tm);
exec.release();
exec = undefined;
print('script done');
Sample 5
bashコマンドを活用して、neqto.js上からシェルスクリプトを直接実行するサンプルです。
Sample 4で使用した「test.sh」をneqto.js上に配置して、直接実行します。
var delay = 10000; //ms
var shellCmd =
"CNT=0\n" +
"while true; do\n" +
"read -t 1 ENTER\n" +
"if [ -n \"$ENTER\" ]; then\n" +
"echo \"$ENTER\"\n" +
"break\n" +
"fi\n" +
"if [ $((${CNT} % 2)) = 1 ]; then\n" +
"echo \"$CNT\" 1>&2\n" +
"else\n" +
"echo \"$CNT\"\n" +
"fi\n" +
"CNT=$((CNT+1))\n" +
"done\n" +
"";
var done = false;
var exec = subprocess.create(['bash', '-c', shellCmd]);
if(!exec) { throw new Error('Subprocess is out of resource'); }
exec.on('stdout', function() {
var str = exec.read();
print('stdout : ' + str.replace(/\n/g, ''));
});
exec.on('stderr', function() {
var str = exec.readError();
print('stderr : ' + str.replace(/\n/g, ''));
});
exec.on('exit', function() {
done = true;
});
exec.execute();
var tm = setTimeout(function() {
exec.write('end\n');
}, delay);
while(1) {
if(done) {
var res = exec.getResult();
print('.exitCode : ' + res.exitCode)
print('.sigNo : ' + res.sigNo)
break;
}
}
clearTimeout(tm);
exec.release();
exec = undefined;
print('script done');