Node.js'de bir kabuk komutunun çıktısını çalıştırın ve alın


113

Bir node.js'de, bir Unix terminal komutunun çıktısını elde etmenin bir yolunu bulmak istiyorum. Bunu yapmanın bir yolu var mı?

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

Bu bir kopya mı yoksa tamamen farklı bir şeyi mi tanımlıyor? stackoverflow.com/questions/7183307/…
Anderson Green

Bu ilginizi çekebilir.
benekastah

Yanıtlar:


143

Şu anda çalıştığım bir projede bunu yapıyorum.

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

Örnek: git kullanıcısını alma

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
Bu işlevin komutun çıktısını döndürmesi mümkün müdür? (Yapmaya çalıştığım buydu.)
Anderson Green

1
bu kodun yaptığı şey bu. Az önce yaptığım düzenlemedeki örneğe bir göz atın
Renato Gama

2
@AndersonGreen Kabuk komutunu eşzamansız olarak çalıştırdığı için, işlevin "dönüş" klavyesiyle normal şekilde dönmesini istemezsiniz. Sonuç olarak, kabuk komutu tamamlandığında çalışması gereken bir kod içeren bir geri aramaya geçmek daha iyidir.
Nick McCurdy

1
Ah, ilk örneğiniz bu geri aramayı çağırdığında bir hata olasılığını yok sayıyor. stdoutBir hata olursa ne olur merak ediyorum . Umarım deterministtir ve belgelenmiştir.
doug65536

31

Child_process'i arıyorsunuz

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'nun belirttiği gibi , şu anda dışarıda bazı eşzamanlı yürütme paketleri de var, aradığınız şeyden daha fazlası olabilecek sync- exec'e bakın. Yine de, node.js'nin tek iş parçacıklı, yüksek performanslı bir ağ sunucusu olacak şekilde tasarlandığını unutmayın; bu nedenle, onu kullanmak istediğiniz şey buysa, yalnızca başlatma sırasında kullanmadığınız sürece, sync-exec benzeri şeylerden uzak durun. ya da başka birşey.


1
Bu durumda komutun çıktısını nasıl elde edebilirim? Komut satırı çıktısını içeren "standart çıktı" mı?
Anderson Green

Ayrıca, geri arama kullanmadan benzer bir şey yapmak mümkün mü?
Anderson Green

Doğru, standart çıktı programın çıktısını içerir. Ve hayır, geri aramalar olmadan yapmak mümkün değil. Node.js'deki her şey, engellemesiz olmaya yöneliktir, yani her IO yaptığınızda geri çağırmaları kullanacaksınız.
hexist

Çıktıyı gerçekten beklemek istediğiniz komut dosyası gibi şeyler yapmak için javascript kullanmak istiyorsanız, v8 kabuğuna bakabilirsiniz, d8
hexist

@hexist Sync, doğal olarak mevcut bazı yöntemler vardır, bu yüzden IMHO'dan kaçınılmalıdır
Renato Gama

30

7.6'dan sonra bir düğüm kullanıyorsanız ve geri arama stilini sevmiyorsanız, temiz bir şekilde okunan kabuk komutlarını almak için node-util'in promisifyişlevini de kullanabilirsiniz async / await. İşte bu tekniği kullanarak kabul edilen cevaba bir örnek:

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

Bu aynı zamanda ele alınabilir başarısız komutlar, bir reddedilen söz dönen yararı vardır try / catchzaman uyumsuz kodu içinde.


Bunu denedin mi { stdout: string, stderr: string }Sonuç olarakawait exec(...)
fwoelffel

1
Evet, bunun size hem stdout hem de stderr dahil tam kabuk çıktısı verdiğini açıklığa kavuşturmalıydım . Sadece çıktıyı istiyorsanız, son satırı değiştirebilir: return { name: name.stdout.trim(), email: email.stdout.trim() }.
Ansikt

16

Renato cevabı sayesinde, gerçekten basit bir örnek oluşturdum:

const exec = require('child_process').exec

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

Sadece global git kullanıcı adınızı yazdıracaktır :)


11

Gereksinimler

Bu, Promises ve Async / Await desteğiyle birlikte Node.js 7 veya sonraki bir sürümünü gerektirir.

Çözüm

Sayfanın davranışını kontrol etmek için vaatlerden yararlanan bir sarmalayıcı işlevi oluşturun. child_process.execKomutun .

Açıklama

Sözler ve eşzamansız bir işlev kullanarak, bir geri arama cehennemine düşmeden ve oldukça düzgün bir API ile çıktıyı döndüren bir kabuğun davranışını taklit edebilirsiniz. awaitAnahtar kelimeyi kullanarak, işinizi child_process.exechalletmeye devam ederken, kolayca okuyan bir komut dosyası oluşturabilirsiniz .

Kod örneği

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

Kullanım

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

Örnek Çıktı

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

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

Çevrimiçi deneyin.

Repl.it .

Dış kaynaklar

Sözler .

child_process.exec.

Node.js destek tablosu .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.