在node.js中执行并获取shell命令的输出

And*_*een 91 shell command-line-interface node.js

在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"
}
Run Code Online (Sandbox Code Playgroud)

Ren*_*ama 119

这就是我在我现在正在工作的项目中的方式.

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

示例:检索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", "") });
        });
    });
};
Run Code Online (Sandbox Code Playgroud)

  • @Boris 你可以自由编辑 9 年前的答案 (4认同)
  • 是否可以使此函数返回命令的输出?(这就是我想要做的.) (2认同)
  • 这就是该代码的作用。看看我刚刚编辑的示例 (2认同)
  • @AndersonGreen你不希望函数通过"返回"键盘正常返回,因为它是异步运行shell命令.因此,最好使用应在shell命令完成时运行的代码传递回调. (2认同)
  • 哎呀,您的第一个示例在调用该回调时忽略了发生错误的可能性。我想知道如果出现错误,“stdout”会发生什么情况。希望是确定性的并有记录。 (2认同)
  • “execute”包装器的意义是什么? (2认同)

hex*_*ist 26

你正在寻找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);
      }
   });
Run Code Online (Sandbox Code Playgroud)

正如雷纳托所指出的那样,现在也有一些同步的exec包,请参阅sync-exec,这可能更像是你正在寻找的东西.请记住,node.js设计为单线程高性能网络服务器,所以如果你想要使用它,请远离sync-exec类似的东西,除非你只是在启动时使用它或者其他的东西.

  • 这种情况下,如何获取命令的输出结果呢?“stdout”是否包含命令行输出? (2认同)

Ans*_*ikt 21

如果您使用的是晚于7.6的节点并且您不喜欢回调样式,那么您还可以使用node-util的promisify函数async / await来获取干净地读取的shell命令.以下是使用此技术的已接受答案的示例:

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 }
};
Run Code Online (Sandbox Code Playgroud)

这还有一个额外的好处,就是在失败的命令上返回被拒绝的promise,这可以try / catch在异步代码中处理.

  • 是的,我应该澄清一下,这为您提供了 _full_ shell 输出,包括 stdout 和 stderr。如果你只想要输出,你可以将最后一行更改为:`return { name: name.stdout.trim(), email: email.stdout.trim() }`。 (5认同)
  • 你试过这个吗?我得到 `{ stdout: string, stderr: string }` 作为 `await exec(...)` 的结果 (2认同)

Ami*_*IRI 17

要求

这将需要支持 Promises 和 Async/Await 的 Node.js 7 或更高版本。

解决方案

创建一个包装函数,利用 promise 来控制child_process.exec命令的行为。

解释

使用 Promise 和异步函数,您可以模拟 shell 返回输出的行为,而不会陷入回调地狱,并且具有非常简洁的 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);
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

用法

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();
Run Code Online (Sandbox Code Playgroud)

样本输出

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

Error: Command failed: cat /etc/shadow
cat: /etc/shadow: Permission denied
Run Code Online (Sandbox Code Playgroud)

在线试一下。

复制

外部资源

承诺

child_process.exec.

Node.js 支持 table

  • 在我看来,这是最干净的选项,让人想起 https://github.com/shelljs/shelljs (但更简单)。 (2认同)

Dam*_*ica 10

感谢Renato的回答,我创建了一个非常基本的示例:

const exec = require('child_process').exec

exec('git config --global user.name', (err, stdout, stderr) => console.log(stdout))
Run Code Online (Sandbox Code Playgroud)

它将只打印您的全局git用户名:)


小智 6

您可以使用 nodejs 附带的 util 库从 exec 命令获取承诺,并可以根据需要使用该输出。使用解构将 stdout 和 stderr 存储在变量中。

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

async function lsExample() {
  const {
    stdout,
    stderr
  } = await exec('ls');
  console.log('stdout:', stdout);
  console.error('stderr:', stderr);
}
lsExample();
Run Code Online (Sandbox Code Playgroud)