it-swarm.com.de

Führen Sie eine Befehlszeilen-Binärdatei 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 nicht sicher, wie ich dies am besten in Node erreichen kann.

Hier ein Beispiel in Ruby, in dem ich PrinceXML anrufe, um eine Datei in eine PDF-Datei zu konvertieren:

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

Was ist der äquivalente Code in Node?

454
Dave Thompson

Für eine noch neuere Version von Node.js (v8.1.4) sind die Ereignisse und Aufrufe ähnlich oder identisch mit älteren Versionen. Es wird jedoch empfohlen, die Standardfunktionen für neuere Sprachen zu verwenden. Beispiele:

Für gepufferte, nicht im Stream formatierte Ausgaben (Sie erhalten alles auf einmal), verwenden Sie 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}`);
});

Sie können es auch mit Versprechungen 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 Sie die Daten schrittweise in Stücken erhalten möchten (Ausgabe als Stream), verwenden Sie 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}`);
});

Beide Funktionen haben ein synchrones Gegenstück. Ein Beispiel für 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');

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

Hinweis: Der folgende Code ist noch funktionsfähig, richtet sich jedoch in erster Linie an Benutzer von ES5 und davor.

Das Modul zum Erzeugen von untergeordneten Prozessen mit Node.js ist in der Dokumentation (v5.0.0) gut dokumentiert. Um einen Befehl auszuführen und seine gesamte Ausgabe als Puffer abzurufen, verwenden Sie 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
});

Wenn Sie die Prozess-E/A für die Verarbeitung mit Streams verwenden müssen, z. B. wenn Sie große Ausgabenmengen erwarten, verwenden Sie 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);

Wenn Sie eine Datei anstelle eines Befehls ausführen, möchten Sie möglicherweise child_process.execFile verwenden. Diese Parameter sind nahezu identisch mit spawn, verfügen jedoch über einen vierten Callback-Parameter wie exec zum Abrufen von Ausgabepuffern. Das könnte ein bisschen so aussehen:

var execFile = require('child_process').execFile;
execFile(file, args, options, function(error, stdout, stderr) {
  // command output is in stdout
});

Seit v0.11.12 unterstützt Node jetzt synchrone spawn und exec. Alle oben beschriebenen Methoden sind asynchron und haben ein synchrones Gegenstück. Dokumentation für sie finden Sie hier . Beachten Sie, dass diese synchronen Methoden im Gegensatz zu den Methoden, die zum asynchronen Erzeugen untergeordneter Prozesse verwendet werden, keine Instanz von ChildProcess zurückgeben.

814
hexacyanide

Knoten JS v11.5.0, LTS v10.14.2 und v8.14.1 --- Dezember 2018

Async und richtige Methode (Unix):

'use strict';

const
    { spawn } = require( 'child_process' ),
    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-Methode (Windows):

'use strict';

const
    { spawn } = require( 'child_process' ),
    dir = spawn( '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' ),
    ls = spawnSync( 'ls', [ '-lh', '/usr' ] );

console.log( `stderr: ${ls.stderr.toString()}` );
console.log( `stdout: ${ls.stdout.toString()}` );

Aus Node.js v11.5.0 Dokumentation

Dasselbe gilt für Node.js v10.14.2 Dokumentation und Node.js v8.14.1 Dokumentation

200
iSkore

Sie suchen 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}`);
        }
});
61
const exec = require("child_process").exec
exec("ls", (error, stdout, stderr) => {
 //do whatever here
})
22
Ben Bieler

Wenn Sie etwas wünschen, das der Top-Antwort sehr ähnlich ist, aber auch synchron ist, funktioniert dies.

var execSync = require('child_process').execSync;
var cmd = "echo 'hello world'";

var options = {
  encoding: 'utf8'
};

console.log(execSync(cmd, options));
14
Cameron

Ich habe gerade einen Cli-Helfer geschrieben, um mit Unix/Windows problemlos umzugehen.

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-Originalquelldatei:

 /**
 * 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. ---------------');
    });
13
Vadorequest

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

const execSync = require('child_process').execSync;

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

Beachten Sie, dass diese Methode die Ereignisschleife blockiert.

12
Pasha Rumkin

Wenn Sie keine Abhängigkeit von einer Abhängigkeit haben und Versprechen verwenden möchten, funktioniert child-process-promise :

installation

npm install child-process-promise --save

exec Verwendung

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-Nutzung

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

Die Antwort von @hexacyanide ist fast vollständig. Unter Windows-Befehl könnte princeprince.exe, prince.cmd, prince.bat oder einfach prince sein (ich weiß nicht, wie Edelsteine ​​gebündelt werden, aber npm-Bins enthalten ein Sh-Skript und ein Batch-Skript - npm und npm.cmd) . Wenn Sie ein portables Skript schreiben möchten, das unter Unix und Windows ausgeführt werden kann, müssen Sie die richtige ausführbare Datei erstellen.

Hier ist eine einfache, aber tragbare Spawn-Funktion:

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;
1
DUzun

Jetzt können Sie shelljs (von Knoten v4) wie folgt verwenden:

var Shell = require('shelljs');

Shell.echo('hello world');
Shell.exec('node --version')
0
FacePalm