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


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/…–
安德森·格林

可能会让您感兴趣。
benekastah 2012年

Answers:


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 2012年

2
@AndersonGreen您不希望该函数使用“返回”键盘正常返回,因为它异步运行shell命令。因此,最好传递一个回调,该回调带有应在shell命令完成时运行的代码。
Nick McCurdy 2013年

1
uch,您的第一个样本在调用该回调时会忽略发生错误的可能性。我想知道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 2012年

请注意,如果您正在寻找使用javascript做脚本类的东西,而您确实想等待输出之类的事情,则可以看看v8 shell,d8
hexist 2012年

@hexist有一些Sync本机可用的方法,即使这样也应避免恕我直言
Renato Gama

29

如果您使用的节点版本晚于7.6,并且您不喜欢回调样式,则还可以使用node-util的promisifyfunction with 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 }
};

这还具有在失败的命令上返回被拒绝的Promise的额外好处,可以try / catch在异步代码内部进行处理。


你有试过吗 我得到的{ stdout: string, stderr: string }await exec(...)
fwoelffel

1
是的,我应该澄清一下,这给了您完整的 shell输出,包括stdout和stderr。如果只需要输出,则可以将最后一行更改为:return { name: name.stdout.trim(), email: email.stdout.trim() }
Ansikt

16

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

const exec = require('child_process').exec

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

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


11

要求

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

创建一个包装函数,该函数利用承诺来控制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);
    });
  });
}

用法

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

在线尝试。

复制

外部资源

承诺

child_process.exec

Node.js支持表

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.