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.