Running external worker process in Node.js
February 5, 2013 Leave a comment
This is example how to properly spawn external worker process in Node.js with error checking. This example runs a ImageMagick convert tool to transform .png image files to 8-bit .png file.
Function spawns ‘convert’ with original file as input and temporary destination path as output and checks the result. If everything seems to be in order, it renames the temporary file over original one.
This also prints out all output from the spawned process to stdout for diagnostics.
var fs = require('fs'), util = require('util'), spawn = require('child_process').spawn; function package_image( path, next ) { // temporary file name. use process PID as part of the name so there // wont' be conflicts if two processes run in parallel var tmpfile = path + '.tmp.' + process.pid; var cmd = 'convert'; // executes command 'convert path -type Palette png8:path.tmp' var convert = spawn(cmd, [ path, '-type', 'Palette', 'png8:' + tmpfile ]); // capture stdout and stderr. Note that convert does not have any output on success convert.stdout.setEncoding('utf8'); convert.stdout.on('data', function (data) { console.log( cmd + ': stdout '+ path + ' ' + data.trim() ); }); convert.stderr.setEncoding('utf8'); convert.stderr.on('data', function (data) { if (/^execvp\(\)/.test(data)) { // we get here if 'convert' command was not found or could // not be executed console.log( cmd + ': failed to start: ' + data ); } else { console.log( cmd + ': stderr '+ path + ' ' + data.trim() ); } }); // hook on process exit convert.on('exit', function( code ) { if ( code ) { // 127 means spawn error, command could not be executed console.log(cmd + ': error '+ path + ' ' + code ); return next(code); } // check if output file exists fs.stat( tmpfile, function(err, info) { if ( err ) { // no file found? something went wrong. Just ignore console.log( cmd + ': output file not found ' + util.inspect(err)); return next( err ); } // check output file size if ( !info.size || !info.isFile() ) { console.log( cmd + ': out file 0 bytes or not a file '+ tmpfile); fs.unlink( tmpfile ); // remove output file return next( true ); } // rename temporary file over original one fs.rename( tmpfile, path, function(err) { if ( err ) { fs.unlink( tmpfile ); console.log( cmd + ': can not rename '+ tmpfile + ' ' + util.inspect(err)); } // done return next( err ); }); }); }); }
Example of usage
package_image( '/tmp/some.png', function(err) { if ( err ) { console.log('Image conversion failed', err ); } });