admin管理员组文章数量:1125904
I am in the process of porting a CLI library from Ruby over to Node.js. In my code I execute several third party binaries when necessary. I am not sure how best to accomplish this in Node.
Here's an example in Ruby where I call PrinceXML to convert a file to a PDF:
cmd = system("prince -v builds/pdf/book.html -o builds/pdf/book.pdf")
What is the equivalent code in Node?
I am in the process of porting a CLI library from Ruby over to Node.js. In my code I execute several third party binaries when necessary. I am not sure how best to accomplish this in Node.
Here's an example in Ruby where I call PrinceXML to convert a file to a PDF:
cmd = system("prince -v builds/pdf/book.html -o builds/pdf/book.pdf")
What is the equivalent code in Node?
Share Improve this question edited Jun 23, 2015 at 10:10 hexacyanide 91.5k31 gold badges165 silver badges162 bronze badges asked Dec 17, 2013 at 19:56 Dave ThompsonDave Thompson 8,8813 gold badges18 silver badges11 bronze badges 3- 4 This library is a good place to start. It allows you to spawn processes across all os platforms. – mattyb Commented Jun 11, 2017 at 5:59
- 3 Possible duplicate of Execute and get the output of a shell command in node.js – Damjan Pavlica Commented Jul 17, 2018 at 12:57
- 5 Simplest is to use child_process.exec, here are some good examples – drorw Commented Apr 18, 2019 at 20:39
12 Answers
Reset to default 1341For even newer version of Node.js (v8.1.4), the events and calls are similar or identical to older versions, but it's encouraged to use the standard newer language features. Examples:
For buffered, non-stream formatted output (you get it all at once), use child_process.exec
:
const { exec } = require('child_process');
exec('cat *.js bad_file | wc -l', (err, stdout, stderr) => {
if (err) {
// node couldn't execute the command
return;
}
// the *entire* stdout and stderr (buffered)
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
You can also use it with Promises:
const util = require('util');
const exec = util.promisify(require('child_process').exec);
async function ls() {
const { stdout, stderr } = await exec('ls');
console.log('stdout:', stdout);
console.log('stderr:', stderr);
}
ls();
If you wish to receive the data gradually in chunks (output as a stream), use child_process.spawn
:
const { spawn } = require('child_process');
const child = spawn('ls', ['-lh', '/usr']);
// use child.stdout.setEncoding('utf8'); if you want text chunks
child.stdout.on('data', (chunk) => {
// data from standard output is here as buffers
});
// since these are streams, you can pipe them elsewhere
child.stderr.pipe(dest);
child.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
Both of these functions have a synchronous counterpart. An example for child_process.execSync
:
const { execSync } = require('child_process');
// stderr is sent to stderr of parent process
// you can set options.stdio if you want it to go elsewhere
let stdout = execSync('ls');
As well as child_process.spawnSync
:
const { spawnSync} = require('child_process');
const child = spawnSync('ls', ['-lh', '/usr']);
console.log('error', child.error);
console.log('stdout ', child.stdout);
console.log('stderr ', child.stderr);
Note: The following code is still functional, but is primarily targeted at users of ES5 and before.
The module for spawning child processes with Node.js is well documented in the documentation (v5.0.0). To execute a command and fetch its complete output as a buffer, use child_process.exec
:
var exec = require('child_process').exec;
var cmd = 'prince -v builds/pdf/book.html -o builds/pdf/book.pdf';
exec(cmd, function(error, stdout, stderr) {
// command output is in stdout
});
If you need to use handle process I/O with streams, such as when you are expecting large amounts of output, use child_process.spawn
:
var spawn = require('child_process').spawn;
var child = spawn('prince', [
'-v', 'builds/pdf/book.html',
'-o', 'builds/pdf/book.pdf'
]);
child.stdout.on('data', function(chunk) {
// output will be here in chunks
});
// or if you want to send output elsewhere
child.stdout.pipe(dest);
If you are executing a file rather than a command, you might want to use child_process.execFile
, which parameters which are almost identical to spawn
, but has a fourth callback parameter like exec
for retrieving output buffers. That might look a bit like this:
var execFile = require('child_process').execFile;
execFile(file, args, options, function(error, stdout, stderr) {
// command output is in stdout
});
As of v0.11.12, Node now supports synchronous spawn
and exec
. All of the methods described above are asynchronous, and have a synchronous counterpart. Documentation for them can be found here. While they are useful for scripting, do note that unlike the methods used to spawn child processes asynchronously, the synchronous methods do not return an instance of ChildProcess
.
Node JS v15.8.0
, LTS v14.15.4
, and v12.20.1
--- Feb 2021
Async method (Unix):
'use strict';
const { spawn } = require( 'child_process' );
const ls = spawn( 'ls', [ '-lh', '/usr' ] );
ls.stdout.on( 'data', ( data ) => {
console.log( `stdout: ${ data }` );
} );
ls.stderr.on( 'data', ( data ) => {
console.log( `stderr: ${ data }` );
} );
ls.on( 'close', ( code ) => {
console.log( `child process exited with code ${ code }` );
} );
Async method (Windows):
'use strict';
const { spawn } = require( 'child_process' );
// NOTE: Windows Users, this command appears to be differ for a few users.
// You can think of this as using Node to execute things in your Command Prompt.
// If `cmd` works there, it should work here.
// If you have an issue, try `dir`:
// const dir = spawn( 'dir', [ '.' ] );
const dir = spawn( 'cmd', [ '/c', 'dir' ] );
dir.stdout.on( 'data', ( data ) => console.log( `stdout: ${ data }` ) );
dir.stderr.on( 'data', ( data ) => console.log( `stderr: ${ data }` ) );
dir.on( 'close', ( code ) => console.log( `child process exited with code ${code}` ) );
Sync:
'use strict';
const { spawnSync } = require( 'child_process' );
const ls = spawnSync( 'ls', [ '-lh', '/usr' ] );
console.log( `stderr: ${ ls.stderr.toString() }` );
console.log( `stdout: ${ ls.stdout.toString() }` );
From Node.js v15.8.0 Documentation
The same goes for Node.js v14.15.4 Documentation and Node.js v12.20.1 Documentation
You are looking for child_process.exec
Here is the example:
const exec = require('child_process').exec;
const child = exec('cat *.js bad_file | wc -l',
(error, stdout, stderr) => {
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
if (error !== null) {
console.log(`exec error: ${error}`);
}
});
Since version 4 the closest alternative is child_process.execSync
method:
const {execSync} = require('child_process');
let output = execSync('prince -v builds/pdf/book.html -o builds/pdf/book.pdf');
⚠️ Note that
execSync
call blocks event loop.
Now you can use shelljs (from node v4) as follows:
var shell = require('shelljs');
shell.echo('hello world');
shell.exec('node --version');
Install with
npm install shelljs
See https://github.com/shelljs/shelljs
const exec = require("child_process").exec
exec("ls", (error, stdout, stderr) => {
//do whatever here
})
If you want something that closely resembles the top answer but is also synchronous then this will work.
var execSync = require('child_process').execSync;
var cmd = "echo 'hello world'";
var options = {
encoding: 'utf8'
};
console.log(execSync(cmd, options));
I just wrote a Cli helper to deal with Unix/windows easily.
Javascript:
define(["require", "exports"], function (require, exports) {
/**
* Helper to use the Command Line Interface (CLI) easily with both Windows and Unix environments.
* Requires underscore or lodash as global through "_".
*/
var Cli = (function () {
function Cli() {}
/**
* Execute a CLI command.
* Manage Windows and Unix environment and try to execute the command on both env if fails.
* Order: Windows -> Unix.
*
* @param command Command to execute. ('grunt')
* @param args Args of the command. ('watch')
* @param callback Success.
* @param callbackErrorWindows Failure on Windows env.
* @param callbackErrorUnix Failure on Unix env.
*/
Cli.execute = function (command, args, callback, callbackErrorWindows, callbackErrorUnix) {
if (typeof args === "undefined") {
args = [];
}
Cli.windows(command, args, callback, function () {
callbackErrorWindows();
try {
Cli.unix(command, args, callback, callbackErrorUnix);
} catch (e) {
console.log('------------- Failed to perform the command: "' + command + '" on all environments. -------------');
}
});
};
/**
* Execute a command on Windows environment.
*
* @param command Command to execute. ('grunt')
* @param args Args of the command. ('watch')
* @param callback Success callback.
* @param callbackError Failure callback.
*/
Cli.windows = function (command, args, callback, callbackError) {
if (typeof args === "undefined") {
args = [];
}
try {
Cli._execute(process.env.comspec, _.union(['/c', command], args));
callback(command, args, 'Windows');
} catch (e) {
callbackError(command, args, 'Windows');
}
};
/**
* Execute a command on Unix environment.
*
* @param command Command to execute. ('grunt')
* @param args Args of the command. ('watch')
* @param callback Success callback.
* @param callbackError Failure callback.
*/
Cli.unix = function (command, args, callback, callbackError) {
if (typeof args === "undefined") {
args = [];
}
try {
Cli._execute(command, args);
callback(command, args, 'Unix');
} catch (e) {
callbackError(command, args, 'Unix');
}
};
/**
* Execute a command no matters what's the environment.
*
* @param command Command to execute. ('grunt')
* @param args Args of the command. ('watch')
* @private
*/
Cli._execute = function (command, args) {
var spawn = require('child_process').spawn;
var childProcess = spawn(command, args);
childProcess.stdout.on("data", function (data) {
console.log(data.toString());
});
childProcess.stderr.on("data", function (data) {
console.error(data.toString());
});
};
return Cli;
})();
exports.Cli = Cli;
});
Typescript original source file:
/**
* Helper to use the Command Line Interface (CLI) easily with both Windows and Unix environments.
* Requires underscore or lodash as global through "_".
*/
export class Cli {
/**
* Execute a CLI command.
* Manage Windows and Unix environment and try to execute the command on both env if fails.
* Order: Windows -> Unix.
*
* @param command Command to execute. ('grunt')
* @param args Args of the command. ('watch')
* @param callback Success.
* @param callbackErrorWindows Failure on Windows env.
* @param callbackErrorUnix Failure on Unix env.
*/
public static execute(command: string, args: string[] = [], callback ? : any, callbackErrorWindows ? : any, callbackErrorUnix ? : any) {
Cli.windows(command, args, callback, function () {
callbackErrorWindows();
try {
Cli.unix(command, args, callback, callbackErrorUnix);
} catch (e) {
console.log('------------- Failed to perform the command: "' + command + '" on all environments. -------------');
}
});
}
/**
* Execute a command on Windows environment.
*
* @param command Command to execute. ('grunt')
* @param args Args of the command. ('watch')
* @param callback Success callback.
* @param callbackError Failure callback.
*/
public static windows(command: string, args: string[] = [], callback ? : any, callbackError ? : any) {
try {
Cli._execute(process.env.comspec, _.union(['/c', command], args));
callback(command, args, 'Windows');
} catch (e) {
callbackError(command, args, 'Windows');
}
}
/**
* Execute a command on Unix environment.
*
* @param command Command to execute. ('grunt')
* @param args Args of the command. ('watch')
* @param callback Success callback.
* @param callbackError Failure callback.
*/
public static unix(command: string, args: string[] = [], callback ? : any, callbackError ? : any) {
try {
Cli._execute(command, args);
callback(command, args, 'Unix');
} catch (e) {
callbackError(command, args, 'Unix');
}
}
/**
* Execute a command no matters what's the environment.
*
* @param command Command to execute. ('grunt')
* @param args Args of the command. ('watch')
* @private
*/
private static _execute(command, args) {
var spawn = require('child_process').spawn;
var childProcess = spawn(command, args);
childProcess.stdout.on("data", function (data) {
console.log(data.toString());
});
childProcess.stderr.on("data", function (data) {
console.error(data.toString());
});
}
}
Example of use:
Cli.execute(Grunt._command, args, function (command, args, env) {
console.log('Grunt has been automatically executed. (' + env + ')');
}, function (command, args, env) {
console.error('------------- Windows "' + command + '" command failed, trying Unix... ---------------');
}, function (command, args, env) {
console.error('------------- Unix "' + command + '" command failed too. ---------------');
});
Use this lightweight npm
package: system-commands
Look at it here.
Import it like this:
const system = require('system-commands')
Run commands like this:
system('ls').then(output => {
console.log(output)
}).catch(error => {
console.error(error)
})
If you don't mind a dependency and want to use promises, child-process-promise
works:
installation
npm install child-process-promise --save
exec Usage
var exec = require('child-process-promise').exec;
exec('echo hello')
.then(function (result) {
var stdout = result.stdout;
var stderr = result.stderr;
console.log('stdout: ', stdout);
console.log('stderr: ', stderr);
})
.catch(function (err) {
console.error('ERROR: ', err);
});
spawn usage
var spawn = require('child-process-promise').spawn;
var promise = spawn('echo', ['hello']);
var childProcess = promise.childProcess;
console.log('[spawn] childProcess.pid: ', childProcess.pid);
childProcess.stdout.on('data', function (data) {
console.log('[spawn] stdout: ', data.toString());
});
childProcess.stderr.on('data', function (data) {
console.log('[spawn] stderr: ', data.toString());
});
promise.then(function () {
console.log('[spawn] done!');
})
.catch(function (err) {
console.error('[spawn] ERROR: ', err);
});
ECMAScript Modules import
...from
syntax
import {exec} from 'child-process-promise';
let result = await exec('echo hi');
console.log(result.stdout);
@hexacyanide's answer is almost a complete one.
On Windows command prince
could be prince.exe
, prince.cmd
, prince.bat
or just prince
(I'm no aware of how gems are bundled, but npm bins come with a sh script and a batch script - npm
and npm.cmd
).
If you want to write a portable script that would run on Unix and Windows, you have to spawn the right executable.
Here is a simple yet portable spawn function:
function spawn(cmd, args, opt) {
var isWindows = /win/.test(process.platform);
if ( isWindows ) {
if ( !args ) args = [];
args.unshift(cmd);
args.unshift('/c');
cmd = process.env.comspec;
}
return child_process.spawn(cmd, args, opt);
}
var cmd = spawn("prince", ["-v", "builds/pdf/book.html", "-o", "builds/pdf/book.pdf"])
// Use these props to get execution results:
// cmd.stdin;
// cmd.stdout;
// cmd.stderr;
Node 16:
const { execSync } = require('child_process');
execSync('ls'); // your system command
本文标签: javascriptExecute a command line binary with NodejsStack Overflow
版权声明:本文标题:javascript - Execute a command line binary with Node.js - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1736675872a1947180.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论