it-swarm.com.de

node.js führt den Systembefehl synchron aus

Ich brauche in node.js Funktion

result = execSync('node -v');

das wird synchron die angegebene Befehlszeile ausführen und alle von diesem Befehlstext ausgegebenen Befehle zurückgeben.

ps. Die Synchronisierung ist falsch. Ich kenne. Nur für den persönlichen Gebrauch.

[~ # ~] Update [~ # ~]

Jetzt haben wir die mgutz-Lösung, die uns Exit-Code gibt, aber nicht stdout! Ich warte immer noch auf eine genauere Antwort.

[~ # ~] Update [~ # ~]

mgutz hat seine Antwort aktualisiert und die Lösung ist hier :)
Wie dgo.a erwähnt, gibt es auch ein eigenständiges Modul exec-sync

UPDATE 30.07.2014

ShellJS lib ist angekommen. Betrachten Sie dies als die beste Wahl für den Moment.


UPDATE 10.02.2015

MINDESTENS! NodeJS 0.12 unterstützt execSync nativ.
Siehe offiziell docs

161
disfated

Node.js (seit Version 0.12 - also für eine Weile) unterstützt execSync :

child_process.execSync(command[, options])

Sie können dies jetzt direkt tun:

const execSync = require('child_process').execSync;
code = execSync('node -v');

und es wird tun, was Sie erwarten. (Standardmäßig werden die E/A-Ergebnisse an den übergeordneten Prozess weitergeleitet.) Beachten Sie, dass Sie jetzt auch spawnSync können.

128

Siehe execSync Bibliothek.

Es ist ziemlich einfach, mit node-ffi umzugehen. Ich würde es nicht für Serverprozesse empfehlen, aber für allgemeine Entwicklungsdienstprogramme wird es erledigt. Installieren Sie die Bibliothek.

npm install node-ffi

Beispielskript:

var FFI = require("node-ffi");
var libc = new FFI.Library(null, {
  "system": ["int32", ["string"]]
});

var run = libc.system;
run("echo $USER");

[EDIT Jun 2012: So erhalten Sie STDOUT]

var lib = ffi.Library(null, {
    // FILE* popen(char* cmd, char* mode);
    popen: ['pointer', ['string', 'string']],

    // void pclose(FILE* fp);
    pclose: ['void', [ 'pointer']],

    // char* fgets(char* buff, int buff, in)
    fgets: ['string', ['string', 'int','pointer']]
});

function execSync(cmd) {
  var
    buffer = new Buffer(1024),
    result = "",
    fp = lib.popen(cmd, 'r');

  if (!fp) throw new Error('execSync error: '+cmd);

  while(lib.fgets(buffer, 1024, fp)) {
    result += buffer.readCString();
  };
  lib.pclose(fp);

  return result;
}

console.log(execSync('echo $HOME'));
54
mgutz

Verwenden Sie das ShellJS Modul.

exec Funktion ohne Rückruf.

Beispiel:

var version = exec('node -v').output;
31
falko

In node.js gibt es ein exzellentes Modul zur Flusskontrolle mit dem Namen asyncblock . Wenn das Umbrechen des Codes in eine Funktion für Ihren Fall in Ordnung ist, kann das folgende Beispiel in Betracht gezogen werden:

var asyncblock = require('asyncblock');
var exec = require('child_process').exec;

asyncblock(function (flow) {
    exec('node -v', flow.add());
    result = flow.wait();
    console.log(result);    // There'll be trailing \n in the output

    // Some other jobs
    console.log('More results like if it were sync...');
});
23
nab

Dies ist in Node.js nicht möglich, da child_process.spawn und child_process.exec wurden von Grund auf so gebaut, dass sie asynchron sind.

Weitere Informationen finden Sie unter: https://github.com/ry/node/blob/master/lib/child_process.js

Wenn Sie diese Blockierung wirklich haben möchten, setzen Sie alles, was danach passieren muss, in einen Rückruf oder erstellen Sie eine eigene Warteschlange, um dies blockierend zu behandeln. Ich nehme an, Sie könnten Async.js für verwenden diese Aufgabe.

Oder, falls Sie viel zu viel Zeit zum Verweilen haben, stöbern Sie in Node.js.

11
Ivo Wetzel

Dies ist der einfachste Weg, den ich gefunden habe:

exec-Sync : https://github.com/jeremyfa/node-exec-sync
(Nicht zu verwechseln mit execSync.)
Führen Sie den Shell-Befehl synchron aus. Verwenden Sie diese Option für Migrationsskripte und CLI-Programme, jedoch nicht für normalen Servercode.

Beispiel:

var execSync = require('exec-sync');   
var user = execSync('echo $USER');
console.log(user);
9
dgo.a

Um das hinzuzufügen, obwohl es nur wenige Verwendungszwecke gibt, in denen Sie sie verwenden sollten, wurden spawnSync/execFileSync/execSync zu node.js in den folgenden Commits hinzugefügt: https://github.com/joyent/node/compare/d58c206862dc...e8df2676748e

7
kvz

Sie können dies mit Fasern erreichen. Wenn Sie beispielsweise meine Common Node library verwenden, sieht der Code folgendermaßen aus:

result = require('subprocess').command('node -v');
5
Oleg

Ich gewöhne mich an die Implementierung von "synchronous" Zeug am Ende der Rückruffunktion. Nicht sehr schön, aber es funktioniert. Wenn Sie eine Folge von Befehlszeilenausführungen implementieren müssen, müssen Sie exec in eine benannte Funktion einbinden und diese rekursiv aufrufen. Dieses Muster scheint für mich brauchbar zu sein:

SeqOfExec(someParam);

function SeqOfExec(somepParam) {
    // some stuff
    // .....
    // .....

    var execStr = "yourExecString";
    child_proc.exec(execStr, function (error, stdout, stderr) {
        if (error != null) {
            if (stdout) {
                throw Error("Smth goes wrong" + error);
            } else {
                // consider that empty stdout causes
                // creation of error object
            }
        }
        // some stuff
        // .....
        // .....

        // you also need some flag which will signal that you 
        // need to end loop
        if (someFlag ) {
            // your synch stuff after all execs
            // here
            // .....
        } else {
            SeqOfExec(someAnotherParam);
        }
    });
};
3
scherka

Ich hatte ein ähnliches Problem und habe dafür eine Node Extension geschrieben. Sie können das Git-Repository auschecken. Es ist Open Source und kostenlos und all das gute Zeug!

https://github.com/aponxi/npm-execxi

ExecXI ist eine Knotenerweiterung, die in C++ geschrieben wurde, um Shell-Befehle einzeln auszuführen und die Ausgabe des Befehls in Echtzeit an die Konsole auszugeben. Optionale verkettete und nicht verkettete Wege sind vorhanden; Das heißt, Sie können das Skript anhalten, nachdem ein Befehl fehlgeschlagen ist (verkettet), oder Sie können so fortfahren, als wäre nichts passiert!

Anweisungen zur Verwendung finden Sie in der ReadMe-Datei . Fühlen Sie sich frei, Pull-Anfragen zu stellen oder Probleme einzureichen!

EDIT:  Die Standardausgabe wird jedoch noch nicht zurückgegeben. Sie wird nur in Echtzeit ausgegeben.  Tut es jetzt. Nun, ich habe es heute gerade veröffentlicht. Vielleicht können wir darauf aufbauen.

Wie auch immer, ich dachte, es wäre wert, es zu erwähnen.

3
Logan

sie können synchrone Shell-Operationen in nodejs wie folgt ausführen:

var execSync = function(cmd) {

    var exec  = require('child_process').exec;
    var fs = require('fs');

    //for linux use ; instead of &&
    //execute your command followed by a simple echo 
    //to file to indicate process is finished
    exec(cmd + " > c:\\stdout.txt && echo done > c:\\sync.txt");

    while (true) {
        //consider a timeout option to prevent infinite loop
        //NOTE: this will max out your cpu too!
        try {
            var status = fs.readFileSync('c:\\sync.txt', 'utf8');

            if (status.trim() == "done") {
                var res = fs.readFileSync("c:\\stdout.txt", 'utf8');
                fs.unlinkSync("c:\\stdout.txt"); //cleanup temp files
                fs.unlinkSync("c:\\sync.txt");
                return res;
            }
        } catch(e) { } //readFileSync will fail until file exists
    }

};

//won't return anything, but will take 10 seconds to run
console.log(execSync("sleep 10")); 

//assuming there are a lot of files and subdirectories, 
//this too may take a while, use your own applicable file path
console.log(execSync("dir /s c:\\usr\\docs\\"));

BEARBEITEN - Dieses Beispiel ist für Windows-Umgebungen gedacht. Passen Sie es bei Bedarf an Ihre eigenen Linux-Anforderungen an

1
Marcus Pope

Ich hatte tatsächlich eine Situation, in der ich mehrere Befehle nacheinander über ein package.json-Vorinstallationsskript ausführen musste, sodass ich mich nicht auf ein Nicht-Core-Modul verlassen konnte.

Das habe ich mir also ausgedacht:

#cmds.coffee
childproc = require 'child_process'

exports.exec = (cmds) ->
  next = ->
    if cmds.length > 0
      cmd = cmds.shift()
      console.log "Running command: #{cmd}"
      childproc.exec cmd, (err, stdout, stderr) ->
        if err? then console.log err
        if stdout? then console.log stdout
        if stderr? then console.log stderr
        next()
    else
      console.log "Done executing commands."

  console.log "Running the follows commands:"
  console.log cmds
  next()

Du kannst es so benutzen:

require('./cmds').exec ['grunt coffee', 'nodeunit test/tls-config.js']

BEARBEITEN: Wie bereits erwähnt, wird die Ausgabe nicht zurückgegeben, und Sie können das Ergebnis der Befehle nicht in einem Node=) - Programm verwenden. Eine weitere Idee ist die Verwendung von LiveScript-Backcalls. http://livescript.net/

1
Jason Livesay