Now much easier (6 years later)!
Spawn returns a childObject with which you can listen for events . Developments:
- Class: ChildProcess
- Event: Error
- Event: Exit
- Event: Close
- Event: Disable
- Event: Message
There are also several objects from childObject , they are:
- Class: ChildProcess
- child.stdin
- child.stdout
- child.stderr
- child.stdio
- child.pid
- child.connected
- child.kill ([signal])
- child.send (message [, sendHandle] [, callback])
- child.disconnect ()
See here for more information on childObject: https://nodejs.org/api/child_process.html.
Asynchronous
If you want to start your process in the background while the node can still continue execution, use the asynchronous method. You can still perform actions after the process is completed and if there are any results.
child_process.spawn (...); (Node 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); });
Here's how you would use the callback + asynchronous method :
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 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); }); }
Using the method described above, you can send each line of script output to the client (for example, using Socket.io to send each line when you receive events on stdout or stderr ).
synchronous
If you want the node to stop working and wait for the script to complete , you can use the synchronous version:
child_process.spawnSync (...); (Node v0.11. 12+)
Problems with this method:
- If the script takes some time, your server will freeze during this time!
- Stdout will be returned only after the script is finished . Since it is synchronous, it cannot continue until the current line ends. Therefore, he cannot capture the 'stdout' event until the spawn line ends.
How to use it:
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);