node.jsでシェルコマンドの実行と出力を取得する


113

node.jsで、Unix端末コマンドの出力を取得する方法を見つけたいのですが。これを行う方法はありますか?

function getCommandOutput(commandString){
    // now how can I implement this function?
    // getCommandOutput("ls") should print the terminal output of the shell command "ls"
}

これは重複ですか、それとも完全に異なる何かを説明していますか?stackoverflow.com/questions/7183307/...
アンダーソングリーン

これはあなたに興味があるかもしれません。
ベネカスタ2012年

回答:


142

それが、現在取り組んでいるプロジェクトでのやり方です。

var exec = require('child_process').exec;
function execute(command, callback){
    exec(command, function(error, stdout, stderr){ callback(stdout); });
};

例:gitユーザーの取得

module.exports.getGitUser = function(callback){
    execute("git config --global user.name", function(name){
        execute("git config --global user.email", function(email){
            callback({ name: name.replace("\n", ""), email: email.replace("\n", "") });
        });
    });
};

3
この関数がコマンドの出力を返すようにすることは可能ですか?(それが私がやろうとしていたことです。)
アンダーソン・グリーン

1
それがそのコードがすることです。先ほど作成した編集の例を見てみましょう
Renato Gama

2
@AndersonGreenシェルコマンドを非同期で実行しているため、「return」キーボードで関数が正常に戻ることを望まないでしょう。結果として、シェルコマンドが完了したときに実行する必要があるコードを含むコールバックを渡すことをお勧めします。
Nick McCurdy

1
痛い、あなたの最初のサンプルは、そのコールバックを呼び出すとき、エラーの可能性を無視します。stdoutエラーが発生したらどうなるのでしょうか。うまくいけば、決定論的で文書化されています。
doug65536

31

あなたはchild_processを探しています

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

child = exec(command,
   function (error, stdout, stderr) {
      console.log('stdout: ' + stdout);
      console.log('stderr: ' + stderr);
      if (error !== null) {
          console.log('exec error: ' + error);
      }
   });

Renatoが指摘しているように、現在いくつかの同期execパッケージもあります。探しているものがもっとあるかもしれないsync-execを参照してください。ただし、node.jsはシングルスレッドの高性能ネットワークサーバーとして設計されているため、起動時にのみ使用する場合を除いて、sync-execには近づかないでください。か何か。


1
この場合、コマンドの出力を取得するにはどうすればよいですか?コマンドライン出力を含む「stdout」はありますか?
アンダーソングリーン

また、コールバックを使用せずに同様のことを行うことは可能ですか?
アンダーソングリーン

正しい、stdoutにはプログラムの出力が含まれています。そして、いいえ、コールバックなしでそれを行うことは不可能です。node.jsのすべての要素は、ノンブロッキングであることに重点を置いています。つまり、IOを実行するたびに、コールバックを使用することになります。
hexist

JavaScriptを使用して、出力を実際に待機したいというちょっとしたことを行う場合は、v8シェルd8
hexist

@hexist Syncネイティブで利用可能ないくつかの方法がありますが、それでも私見は避ける必要があります
Renato Gama

29

7.6以降のノードを使用していて、コールバックスタイルが気に入らない場合は、node-utilのpromisify関数を使用しasync / awaitて、きれいに読み取るシェルコマンドを取得することもできます。このテクニックを使用した、受け入れられた回答の例を次に示します。

const { promisify } = require('util');
const exec = promisify(require('child_process').exec)

module.exports.getGitUser = async function getGitUser () {
  const name = await exec('git config --global user.name')
  const email = await exec('git config --global user.email')
  return { name, email }
};

これには、失敗したコマンドに対して拒否されたpromiseを返すという追加の利点もあります。これはtry / catch、非同期コード内で処理できます。


これを試しましたか?{ stdout: string, stderr: string }結果として、await exec(...)
fwoelffelが

1
ええ、これでstdoutとstderrの両方を含む完全なシェル出力が得られることを明確にしたはずです。出力だけが必要な場合は、最後の行を次のように変更できますreturn { name: name.stdout.trim(), email: email.stdout.trim() }
Ansikt

16

レナートの回答のおかげで、私は本当に基本的な例を作成しました:

const exec = require('child_process').exec

exec('git config --global user.name', (err, stdout, stderr) => console.log(stdout))

それはあなたのグローバルgitユーザー名を表示するだけです:)


11

必要条件

これには、PromiseおよびAsync / AwaitをサポートするNode.js 7以降が必要です。

解決

child_process.execコマンドの動作を制御するためにpromiseを活用するラッパー関数を作成します。

説明

promiseと非同期関数を使用すると、コールバックの地獄に陥ることなく、かなりきちんとしたAPIを使用して、出力を返すシェルの動作を模倣できます。awaitキーワードを使用すると、作業をchild_process.exec完了しながら、読みやすいスクリプトを作成できます。

コードサンプル

const childProcess = require("child_process");

/**
 * @param {string} command A shell command to execute
 * @return {Promise<string>} A promise that resolve to the output of the shell command, or an error
 * @example const output = await execute("ls -alh");
 */
function execute(command) {
  /**
   * @param {Function} resolve A function that resolves the promise
   * @param {Function} reject A function that fails the promise
   * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
   */
  return new Promise(function(resolve, reject) {
    /**
     * @param {Error} error An error triggered during the execution of the childProcess.exec command
     * @param {string|Buffer} standardOutput The result of the shell command execution
     * @param {string|Buffer} standardError The error resulting of the shell command execution
     * @see https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback
     */
    childProcess.exec(command, function(error, standardOutput, standardError) {
      if (error) {
        reject();

        return;
      }

      if (standardError) {
        reject(standardError);

        return;
      }

      resolve(standardOutput);
    });
  });
}

使用法

async function main() {
  try {
    const passwdContent = await execute("cat /etc/passwd");

    console.log(passwdContent);
  } catch (error) {
    console.error(error.toString());
  }

  try {
    const shadowContent = await execute("cat /etc/shadow");

    console.log(shadowContent);
  } catch (error) {
    console.error(error.toString());
  }
}

main();

出力例

root:x:0:0::/root:/bin/bash
[output trimmed, bottom line it succeeded]

Error: Command failed: cat /etc/shadow
cat: /etc/shadow: Permission denied

オンラインでお試しください。

Repl.it

外部リソース

約束

child_process.exec

Node.jsサポートテーブル

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.