「hi」を出力する、1秒間スリープする、「hi」を出力する、1秒間スリープするなどのスクリプトがあります。今、私はこのモデルでこの問題に取り組むことができると思った。
var spawn = require('child_process').spawn,
temp = spawn('PATH TO SCRIPT WITH THE ABOVE BEHAVIOUR');
temp.stdout.pipe(process.stdout);
問題は、出力を表示するためにタスクを終了する必要があることです。私が理解しているように、これは新しく生成されたプロセスが実行制御を行うという事実によるものです。明らかにnode.jsはスレッドをサポートしていませんので、ソリューションはありますか?私の考えは、2つのインスタンスを実行することでした。1つはタスクを作成するという特定の目的のためで、2つ目のインスタンスのプロセスに出力をパイプして、これを達成できると考えました。
まだNode.jsで足を濡らしていますが、いくつかのアイデアがあります。まず、execFile
の代わりにspawn
を使用する必要があると思います。 execFile
はスクリプトへのパスがある場合に使用し、spawn
はNode.jsがシステムパスに対して解決できる既知のコマンドを実行するために使用します。
var child = require('child_process').execFile('path/to/script', [
'arg1', 'arg2', 'arg3',
], function(err, stdout, stderr) {
// Node.js will invoke this callback when process terminates.
console.log(stdout);
});
var child = require('child_process').execFile('path/to/script', [
'arg1', 'arg2', 'arg3' ]);
// use event hooks to provide a callback to execute when data are available:
child.stdout.on('data', function(data) {
console.log(data.toString());
});
さらに、生成されたプロセスをNodeの制御端末から切り離すことができ、非同期で実行できるオプションがあるようです。私はまだこれをテストしていませんが、 API docs には次のような例があります:
child = require('child_process').execFile('path/to/script', [
'arg1', 'arg2', 'arg3',
], {
// detachment and ignored stdin are the key here:
detached: true,
stdio: [ 'ignore', 1, 2 ]
});
// and unref() somehow disentangles the child's event loop from the parent's:
child.unref();
child.stdout.on('data', function(data) {
console.log(data.toString());
});
今ではずっと簡単です(6年後)!
SpawnはchildObjectを返します。これはイベントを聞くとともに使用できます。イベントは次のとおりです。
たくさんのchildObjectからのオブジェクトもあり、それらは:
ChildObjectの詳細については、こちらをご覧ください: https://nodejs.org/api/child_process.html
ノードが実行を継続できる間にバックグラウンドでプロセスを実行する場合は、非同期メソッドを使用します。プロセスの完了後、およびプロセスに何らかの出力がある場合(たとえば、スクリプトの出力をクライアントに送信する場合)、アクションを実行することを選択できます。
child_process.spawn(...); (ノードv0.1.90)
var spawn = require('child_process').spawn;
var child = spawn('node ./commands/server.js');
// You can also use a variable to save the output
// for when the script closes later
var scriptOutput = "";
child.stdout.setEncoding('utf8');
child.stdout.on('data', function(data) {
//Here is where the output goes
console.log('stdout: ' + data);
data=data.toString();
scriptOutput+=data;
});
child.stderr.setEncoding('utf8');
child.stderr.on('data', function(data) {
//Here is where the error output goes
console.log('stderr: ' + data);
data=data.toString();
scriptOutput+=data;
});
child.on('close', function(code) {
//Here you can get the exit code of the script
console.log('closing code: ' + code);
console.log('Full output of script: ',scriptOutput);
});
コールバック+非同期メソッドの使用方法:
var child_process = require('child_process');
console.log("Node Version: ", process.version);
run_script("ls", ["-l", "/home"], function(output, exit_code) {
console.log("Process Finished.");
console.log('closing code: ' + exit_code);
console.log('Full output of script: ',output);
});
console.log ("Continuing to do node things while the process runs at the same time...");
// This function will output the lines from the script
// AS is runs, AND will return the full combined output
// as well as exit code when it's done (using the callback).
function run_script(command, args, callback) {
console.log("Starting Process.");
var child = child_process.spawn(command, args);
var scriptOutput = "";
child.stdout.setEncoding('utf8');
child.stdout.on('data', function(data) {
console.log('stdout: ' + data);
data=data.toString();
scriptOutput+=data;
});
child.stderr.setEncoding('utf8');
child.stderr.on('data', function(data) {
console.log('stderr: ' + data);
data=data.toString();
scriptOutput+=data;
});
child.on('close', function(code) {
callback(scriptOutput,code);
});
}
上記の方法を使用すると、スクリプトからのすべての出力行をクライアントに送信できます(たとえば、stdout
またはstderr
でイベントを受信すると、Socket.ioを使用して各行を送信します)。
Nodeが実行していることを停止し、スクリプトが完了するまで待機するが必要な場合は、同期バージョンを使用できます。
child_process.spawnSync(...); (ノードv0.11.12 +)
この方法の問題:
それを使用する方法:
var child_process = require('child_process');
var child = child_process.spawnSync("ls", ["-l", "/home"], { encoding : 'utf8' });
console.log("Process finished.");
if(child.error) {
console.log("ERROR: ",child.error);
}
console.log("stdout: ",child.stdout);
console.log("stderr: ",child.stderr);
console.log("exist code: ",child.status);
ここに私が見つけた最もクリーンなアプローチがあります:
require("child_process").spawn('bash', ['./script.sh'], {
cwd: process.cwd(),
detached: true,
stdio: "inherit"
});
子プロセスでnpmを生成したときに、「npm install」コマンドからログ出力を取得するのに少し問題がありました。依存関係のリアルタイムロギングが親コンソールに表示されませんでした。
元のポスターが望んでいることを行う最も簡単な方法は次のようです(Windowsでnpmを起動し、すべてを親コンソールに記録します)。
var args = ['install'];
var options = {
stdio: 'inherit' //feed all child process logging into parent process
};
var childProcess = spawn('npm.cmd', args, options);
childProcess.on('close', function(code) {
process.stdout.write('"npm install" finished with code ' + code + '\n');
});
子:
setInterval(function() {
process.stdout.write("hi");
}, 1000); // or however else you want to run a timer
親:
require('child_process').fork('./childfile.js');
// fork'd children use the parent's stdio
std-pour と呼ばれるライブラリにパッケージ化するのに十分な頻度でこの機能を必要としていることに気付きました。コマンドを実行し、リアルタイムで出力を表示できます。単純にインストールするには:
npm install std-pour
それから、コマンドを実行して出力をリアルタイムで見るのに十分簡単です:
const { pour } = require('std-pour');
pour('ping', ['8.8.8.8', '-c', '4']).then(code => console.log(`Error Code: ${code}`));
複数のコマンドを連鎖できるように約束されています。それは child_process.spawn
との関数署名にも対応しているので、それを使用している場所ならどこでも置き換えられるはずです。
child_process.exec
に関連する答えを追加すると、私もライブフィードバックが必要になり、スクリプトが終了するまで何も得られませんでした。これは、受け入れられた回答に対する私のコメントも補足しますが、フォーマットされているので、少し理解しやすく、読みやすくなります。
基本的には、Gulpを呼び出すnpmスクリプトがあり、その後child_process.exec
を使用してタスクを呼び出し、OSに応じてbashまたはバッチスクリプトを実行します。どちらのスクリプトもGulpを介してビルドプロセスを実行し、Gulp出力で動作するいくつかのバイナリを呼び出します。
それは他のもの(スポーンなど)とまったく同じですが、完了のために、正確にそれを行う方法があります:
// INCLUDES
import * as childProcess from 'child_process'; // ES6 Syntax
// GLOBALS
let exec = childProcess.exec; // Or use 'var' for more proper
// semantics, though 'let' is
// true-to-scope
// Assign exec to a variable, or chain stdout at the end of the call
// to exec - the choice, yours (i.e. exec( ... ).stdout.on( ... ); )
let childProcess = exec
(
'./binary command -- --argument argumentValue',
( error, stdout, stderr ) =>
{
if( error )
{
// This won't show up until the process completes:
console.log( '[ERROR]: "' + error.name + '" - ' + error.message );
console.log( '[STACK]: ' + error.stack );
console.log( stdout );
console.log( stderr );
callback(); // Gulp stuff
return;
}
// Neither will this:
console.log( stdout );
console.log( stderr );
callback(); // Gulp stuff
}
);
イベントリスナを追加するのと同じくらい簡単になりました。 stdout
の場合:
childProcess.stdout.on
(
'data',
( data ) =>
{
// This will render 'live':
console.log( '[STDOUT]: ' + data );
}
);
stderr
の場合:
childProcess.stderr.on
(
'data',
( data ) =>
{
// This will render 'live' too:
console.log( '[STDERR]: ' + data );
}
);
悪くない-HTH