853 Stimmen

Führen Sie ein Befehlszeilen-Binär mit Node.js aus

Ich bin dabei, eine CLI-Bibliothek von Ruby auf Node.js zu portieren. In meinem Code führe ich bei Bedarf mehrere Drittanbieter-Binärdateien aus. Ich bin mir nicht sicher, wie ich dies am besten in Node erreichen kann.

Hier ist ein Beispiel in Ruby, bei dem ich PrinceXML aufrufe, um eine Datei in eine PDF umzuwandeln:

cmd = system("prince -v builds/pdf/book.html -o builds/pdf/book.pdf")

Was ist der entsprechende Code in Node?

1327voto

hexacyanide Punkte 85956

Für noch neuere Versionen von Node.js (v8.1.4) sind die Ereignisse und Aufrufe ähnlich oder identisch zu älteren Versionen, jedoch wird empfohlen, die standardmäßigen neueren Sprachfunktionen zu verwenden. Beispiele:

Für gepufferte, nicht streamformatierte Ausgabe (du bekommst alles auf einmal), verwende 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}`);
});

Du kannst es auch mit Promises verwenden:

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();

Wenn du die Daten schrittweise in Chunks erhalten möchtest (Ausgabe als Stream), verwende 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
});

// da dies Streams sind, kannst du sie anderswohin umleiten
child.stderr.pipe(dest);

child.on('close', (code) => {
  console.log(`Kindprozess wurde beendet mit Code ${code}`);
});

Beide dieser Funktionen haben eine synchrone Entsprechung. Ein Beispiel für child_process.execSync:

const { execSync } = require('child_process');
// stderr wird an den stderr des übergeordneten Prozesses gesendet
// du kannst Optionen.stdio setzen, wenn du willst, dass es woanders hingeht
let stdout = execSync('ls');

Sowie child_process.spawnSync:

const { spawnSync} = require('child_process');
const child = spawnSync('ls', ['-lh', '/usr']);

console.log('Fehler', child.error);
console.log('stdout ', child.stdout);
console.log('stderr ', child.stderr);

Hinweis: Der folgende Code ist zwar funktionsfähig, richtet sich jedoch hauptsächlich an Benutzer von ES5 und davor.

Das Modul zum Starten von Kindprozessen mit Node.js ist gut dokumentiert in der Dokumentation (v5.0.0). Um einen Befehl auszuführen und seine vollständige Ausgabe als Puffer zu erhalten, verwende 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) {
  // Befehlsausgabe befindet sich in stdout
});

Wenn du Prozess I/O mit Streams handhaben musst, z. B. wenn du mit großen Datenmengen rechnest, verwende 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) {
  // Ausgabe wird hier in Chunks sein
});

// oder wenn du die Ausgabe anderswohin senden möchtest
child.stdout.pipe(dest);

Wenn du eine Datei ausführst anstelle eines Befehls, möchtest du vielleicht child_process.execFile verwenden, das Parameter hat, die nahezu identisch mit spawn sind, aber einen vierten Rückrufparameter wie exec hat, um Ausgabepuffer abzurufen. Das könnte ungefähr so aussehen:

var execFile = require('child_process').execFile;
execFile(file, args, options, function(error, stdout, stderr) {
  // Befehlsausgabe befindet sich in stdout
});

Ab v0.11.12 unterstützt Node nun synchrones spawn und exec. Alle oben beschriebenen Methoden sind asynchron und haben eine synchrone Entsprechung. Die Dokumentation dazu findest du hier. Obwohl sie nützlich für Skripting sind, beachte, dass im Gegensatz zu den Methoden, die Kindprozesse asynchron erstellen, die synchronen Methoden keine Instanz von ChildProcess zurückgeben.

322voto

iSkore Punkte 6976

Node JS v15.8.0, LTS v14.15.4, and v12.20.1 --- Feb 2021

Async-Methode (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( `Kindprozess beendet mit Code ${ code }` );
} );

Async-Methode (Windows):

'use strict';

const { spawn } = require( 'child_process' );
// HINWEIS: Windows-Benutzer, dieses Kommando scheint sich bei einigen Benutzern zu unterscheiden.
// Sie können dies so betrachten, als würde Node Dinge in Ihrer Eingabeaufforderung ausführen.
// Wenn `cmd` dort funktioniert, sollte es hier funktionieren.
// Wenn Sie ein Problem haben, versuchen Sie `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( `Kindprozess beendet mit 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() }` );

Von Node.js v15.8.0 Dokumentation

Dasselbe gilt für Node.js v14.15.4 Dokumentation und Node.js v12.20.1 Dokumentation

89voto

Andrei Karpushonak Punkte 8630

Du suchst nach child_process.exec

Hier ist das Beispiel:

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}`);
        }
});

50voto

Paul Rumkin Punkte 6307

Seit Version 4 ist die nächstgelegene Alternative die child_process.execSync Methode:

const {execSync} = require('child_process');

let output = execSync('prince -v builds/pdf/book.html -o builds/pdf/book.pdf');

Beachten Sie, dass der execSync Aufruf die Ereignisschleife blockiert.

36voto

FacePalm Punkte 9396

Jetzt können Sie shelljs (ab node v4) wie folgt verwenden:

var shell = require('shelljs');

shell.echo('hello world');
shell.exec('node --version');

Installieren mit

npm install shelljs

Siehe https://github.com/shelljs/shelljs

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X