Execute and get the output of a shell command in node.js

前端 未结 5 499
无人及你
无人及你 2020-11-27 10:56

In a node.js, I\'d like to find a way to obtain the output of a Unix terminal command. Is there any way to do this?

function getCommandOutput(commandString){         


        
相关标签:
5条回答
  • 2020-11-27 11:12

    This is the method I'm using in a project I am currently working on.

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

    Example of retrieving a git user:

    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", "") });
            });
        });
    };
    
    0 讨论(0)
  • 2020-11-27 11:15

    Requirements

    This will require Node.js 7 or later with a support for Promises and Async/Await.

    Solution

    Create a wrapper function that leverage promises to control the behavior of the child_process.exec command.

    Explanation

    Using promises and an asynchronous function, you can mimic the behavior of a shell returning the output, without falling into a callback hell and with a pretty neat API. Using the await keyword, you can create a script that reads easily, while still be able to get the work of child_process.exec done.

    Code sample

    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);
        });
      });
    }
    

    Usage

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

    Sample Output

    root:x:0:0::/root:/bin/bash
    [output trimmed, bottom line it succeeded]
    
    Error: Command failed: cat /etc/shadow
    cat: /etc/shadow: Permission denied
    

    Try it online.

    Repl.it.

    External resources

    Promises.

    child_process.exec.

    Node.js support table.

    0 讨论(0)
  • 2020-11-27 11:25

    If you're using node later than 7.6 and you don't like the callback style, you can also use node-util's promisify function with async / await to get shell commands which read cleanly. Here's an example of the accepted answer, using this technique:

    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 }
    };
    

    This also has the added benefit of returning a rejected promise on failed commands, which can be handled with try / catch inside the async code.

    0 讨论(0)
  • 2020-11-27 11:26

    You're looking for 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);
          }
       });
    

    As pointed out by Renato, there are some synchronous exec packages out there now too, see sync-exec that might be more what yo're looking for. Keep in mind though, node.js is designed to be a single threaded high performance network server, so if that's what you're looking to use it for, stay away from sync-exec kinda stuff unless you're only using it during startup or something.

    0 讨论(0)
  • 2020-11-27 11:33

    Thanks to Renato answer, I have created a really basic example:

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

    It will just print your global git username :)

    0 讨论(0)
提交回复
热议问题