exec-sh.js
1 var cp = require('child_process') 2 3 var defSpawnOptions = { stdio: 'inherit' } 4 5 /** 6 * @summary Get shell program meta for current platform 7 * @private 8 * @returns {Object} 9 */ 10 function getShell () { 11 if (process.platform === 'win32') { 12 return { cmd: 'cmd', arg: '/C' } 13 } else { 14 return { cmd: 'sh', arg: '-c' } 15 } 16 } 17 18 /** 19 * Callback is called with the output when the process terminates. Output is 20 * available when true is passed as options argument or stdio: null set 21 * within given options. 22 * 23 * @summary Execute shell command forwarding all stdio 24 * @param {String|Array} command 25 * @param {Object|TRUE} [options] spawn() options or TRUE to set stdio: null 26 * @param {Function} [callback] 27 * @returns {ChildProcess} 28 */ 29 function execSh (command, options, callback) { 30 if (Array.isArray(command)) { 31 command = command.join(';') 32 } 33 34 if (options === true) { 35 options = { stdio: null } 36 } 37 38 if (typeof options === 'function') { 39 callback = options 40 options = defSpawnOptions 41 } else { 42 options = options || {} 43 options = Object.assign({}, defSpawnOptions, options) 44 callback = callback || function () {} 45 } 46 47 var child 48 var stdout = '' 49 var stderr = '' 50 var shell = getShell() 51 52 try { 53 child = cp.spawn(shell.cmd, [shell.arg, command], options) 54 } catch (e) { 55 callback(e, stdout, stderr) 56 return 57 } 58 59 if (child.stdout) { 60 child.stdout.on('data', function (data) { 61 stdout += data 62 }) 63 } 64 65 if (child.stderr) { 66 child.stderr.on('data', function (data) { 67 stderr += data 68 }) 69 } 70 71 child.on('close', function (code) { 72 if (code) { 73 var e = new Error('Shell command exit with non zero code: ' + code) 74 e.code = code 75 callback(e, stdout, stderr) 76 } else { 77 callback(null, stdout, stderr) 78 } 79 }) 80 81 return child 82 } 83 84 execSh.promise = function (command, options) { 85 return new Promise(function (resolve, reject) { 86 execSh(command, options, function (err, stdout, stderr) { 87 if (err) { 88 err.stdout = stdout 89 err.stderr = stderr 90 return reject(err) 91 } 92 93 resolve({ 94 stderr: stderr, 95 stdout: stdout 96 }) 97 }) 98 }) 99 } 100 101 module.exports = execSh