web-dev-qa-db-ja.com

node.jsはシステムコマンドを同期的に実行します

node.js関数で必要です

result = execSync('node -v');

これは、指定されたコマンドラインをsynchronously実行し、そのコマンドテキストによってすべての標準出力を返します。

追伸同期が間違っています。知っている。個人使用のみ。

UPDATE

これで、終了コードを提供するmgutzのソリューションがありますが、stdoutはありません!より正確な答えを待っています。

UPDATE

mgutzは彼の答えを更新し、解決策はこちらです:)
また、dgo.aが述べたように、スタンドアロンモジュール exec-sync があります

2014-07-30更新

ShellJS libが到着しました。今のところこれが最良の選択だと考えてください。


2015-02-10更新

AT LAST!NodeJS 0.12はexecSyncをネイティブにサポートします。
公式を参照してください docs

157
disfated

Node.js(バージョン0.12以降-しばらくの間)が execSync をサポートします:

child_process.execSync(command[, options])

これを直接行うことができます:

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

期待どおりに動作します。 (デフォルトでは、I/O結果を親プロセスにパイプします)。 spawnSync を使用することもできます。

122

execSync libraryを参照してください。

node-ffi を使用すると非常に簡単です。私はサーバープロセスにはお勧めしませんが、一般的な開発ユーティリティの場合はうまくいきます。ライブラリをインストールします。

npm install node-ffi

サンプルスクリプト:

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

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

[2012年6月編集: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

ShellJS モジュールを使用します。

exec コールバックを提供しない機能。

例:

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

Node.jsには asyncblock と呼ばれるフロー制御用の優れたモジュールがあります。コードを関数でラップしても問題ない場合は、次のサンプルを検討してください。

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

これはNode.jsでは不可能です。child_process.spawnchild_process.execの両方は、非同期になるように一から構築されました。

詳細については、 https://github.com/ry/node/blob/master/lib/child_process.js

このブロッキングを本当にしたい場合は、コールバックに後で発生する必要があるすべてのものを配置するか、これをブロッキング形式で処理する独自のキューを構築します。 Async.js forこの仕事。

または、あまりにも多くの時間を費やす場合は、Node.jsをハックしてください。

11
Ivo Wetzel

これは私が見つけた最も簡単な方法です:

exec-Synchttps://github.com/jeremyfa/node-exec-sync
(execSyncと混同しないでください。)
シェルコマンドを同期的に実行します。これを移行スクリプト、cliプログラムに使用しますが、通常のサーバーコードには使用しません。

例:

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

これらを使用するユースケースがほとんどないにもかかわらず、それを追加するために、これらのコミットでspawnSync/execFileSync/execSyncがnode.jsに追加されました: https://github.com/joyent/node/compare/d58c206862dc ... e8df2676748e

7
kvz

これは、繊維を使用して実現できます。たとえば、my Common Node library を使用すると、コードは次のようになります。

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

コールバック関数の最後に"synchronous"を実装することに慣れました。あまりいいとは言えませんが、うまくいきます。一連のコマンドライン実行を実装する必要がある場合は、execを名前付き関数にラップして、再帰的に呼び出す必要があります。このパターンは私にとって有用なようです:

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

私は同様の問題を抱えていたため、このためにノード拡張を作成することになりました。 gitリポジトリをチェックアウトできます。それはオープンソースで無料であり、すべてのものが良いものです!

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

ExecXIは、シェルコマンドを1つずつ実行し、コマンドの出力をリアルタイムでコンソールに出力するために、C++で記述されたノード拡張です。オプションの連鎖および非連鎖の方法があります。つまり、コマンドが失敗した(連鎖)後にスクリプトを停止するか、何も起こらなかったように続行することを選択できます。

使用方法は ReadMeファイル にあります。プルリクエストを行ったり、問題を送信したりしてください。

編集: ただし、まだ標準出力は返されません...リアルタイムで出力するだけです。 今はそうです。さて、今日リリースしました。たぶん私たちはそれに基づいて構築することができます。

とにかく、私はそれを言及する価値があると思いました。

3
Logan

nodejsで次のように同期シェル操作を実行できます。

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\\"));

編集-この例はWindows環境向けであり、必要に応じて独自のLinuxのニーズに合わせて調整します

1
Marcus Pope

実際には、package.jsonプレインストールスクリプトから複数のコマンドをWindowsとLinux/OSXの両方で動作する方法で次々に実行する必要があったため、非コアモジュールに頼ることができませんでした。

だからこれは私が思いついたものです:

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

次のように使用できます。

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

編集:指摘したように、これは実際に出力を返さないか、Nodeプログラムでコマンドの結果を使用できるようにしません。そのためのもう1つのアイデアは、LiveScriptバックコールを使用することです。 http://livescript.net/

1
Jason Livesay