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

wko9yo5t  于 2022-11-22  发布在  Node.js
关注(0)|答案(8)|浏览(353)

在一个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"
}
vxqlmq5t

vxqlmq5t1#

这是我目前正在进行的一个项目中使用的方法。

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", "") });
        });
    });
};
7rtdyuoh

7rtdyuoh2#

如果你使用的是node 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 () {
  // Exec output contains both stderr and stdout outputs
  const nameOutput = await exec('git config --global user.name')
  const emailOutput = await exec('git config --global user.email')

  return { 
    name: nameOutput.stdout.trim(), 
    email: emailOutput.stdout.trim()
  }
};

这还有一个额外的好处,即在失败的命令上返回一个被拒绝的承诺,这可以在异步代码中用try / catch来处理。

kupeojn6

kupeojn63#

您正在寻找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所指出的,现在也有一些同步执行包,请参阅sync-exec,它可能更符合您的需求。但请记住,node.js是为单线程高性能网络服务器而设计的,因此如果您希望使用它,请远离sync-exec之类的东西,除非您只在启动时使用它。

iecba09b

iecba09b4#

要求

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

溶液

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

说明

使用promises和一个异步函数,你可以模仿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

在线试用。

Repl.it

外部资源

是的。
child_process.exec.
Node.js support table

wj8zmpe1

wj8zmpe15#

由于雷纳托的回答,我创造了一个真正基本的例子:

const exec = require('child_process').exec

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

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

1yjd4xko

1yjd4xko6#

可以使用nodejs附带的util库从exec命令中获得一个承诺,并可以根据需要使用该输出。

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();
a7qyws3x

a7qyws3x7#

您可以使用ShellJS包。
ShellJS是在Node.js API之上的Unix shell命令的可移植(Windows/Linux/OS X)实现。
请参阅https://www.npmjs.com/package/shelljs#execcommand--options--callback

import * as shell from "shelljs";

//usage:
//exec(command [, options] [, callback])

//example:
const version = shell.exec("node --version", {async: false}).stdout;
console.log("nodejs version", version);
mi7gmzs6

mi7gmzs68#

下面是接受的答案的async await TypeScript实现:

const execute = async (command: string): Promise<any> => {
  return new Promise((resolve, reject) => {
    const exec = require("child_process").exec;
    exec(
      command,
      function (
        error: Error,
        stdout: string | Buffer,
        stderr: string | Buffer
      ) {
        if (error) {
          reject(error);
          return;
        }
        if (stderr) {
          reject(stderr);
          return;
        } else {
          resolve(stdout);
        }
      }
    );
  });
};

相关问题