web-dev-qa-db-fra.com

Exécuter et obtenir le résultat d'une commande Shell dans node.js

Dans un fichier node.js, j'aimerais trouver un moyen d'obtenir le résultat d'une commande de terminal Unix. Est-ce qu'il y a un moyen de faire ça?

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

C’est ce que je fais dans un projet que je travaille maintenant.

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

Exemple: Récupération d'un utilisateur 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", "") });
        });
    });
};
116
Renato Gama

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

Comme Renato l’a souligné, il existe également des packages d’exécution synchrone, voir sync-exec , ce qui pourrait être davantage ce que vous cherchez. Gardez à l'esprit cependant que node.js est conçu pour être un serveur réseau hautes performances mono-thread, donc si c'est ce que vous cherchez à utiliser, évitez les types de synchronisation sync-exec, sauf si vous ne l'utilisez que lors du démarrage ou quelque chose.

25
hexist

Si vous utilisez un noeud postérieur à 7.6 et que vous n'aimez pas le style de rappel, vous pouvez également utiliser la fonction promisify de node-util avec async / await pour obtenir des commandes Shell qui lisent proprement. Voici un exemple de réponse acceptée, utilisant cette 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 }
};

Cela présente également l’avantage supplémentaire de renvoyer une promesse rejetée sur des commandes ayant échoué, qui peut être gérée avec try / catch à l'intérieur du code asynchrone.

17
Ansikt

Grâce à Renato answer, j'ai créé un exemple très basique:

const exec = require('child_process').exec

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

Cela imprimera simplement votre nom d'utilisateur git global :)

9
Damjan Pavlica

Exigences

Cela nécessitera Node.js 7 ou version ultérieure avec un support pour Promises et Async/Await.

Solution

Créer une fonction wrapper qui exploite promet de contrôler le comportement du child_process.exec commande.

Explication

En utilisant des promesses et une fonction asynchrone, vous pouvez imiter le comportement d’un Shell renvoyant la sortie, sans tomber dans un enfer de rappel et avec une API très soignée. En utilisant le mot-clé await, vous pouvez créer un script qui se lit facilement tout en conservant le travail de child_process.exec terminé.

Échantillon de code

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

Exemple de sortie

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

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

Essayez-le en ligne.

Repl.it .

Ressources externes

promesses .

child_process.exec .

table de support Node.js .

0
Amin NAIRI