簡體   English   中英

用於異步Linux腳本的Node.js

[英]Node.js for Asynchronous Linux Scripting

在我寫的其他程序中,我很喜歡使用promises的node.js的異步方面。

我想對Linux腳本使用相同的編程風格(使用node.js)。 換句話說,我希望能夠同時執行多個Linux命令,然后在這些命令完成后,我希望node.js腳本能夠異步執行另一組命令(依此類推)。

我遇到了一個aritlce ,它展示了如何使用node.js執行同步Linux命令,但是我還沒有找到一個類似的教程,它涵蓋了使用node.js管理多個異步Linux命令。

這目前可能嗎? 如果是這樣,你能指導我一些可以幫助我開始實現這一目標的特定資源嗎?

我不確定我是不對,但我認為你正在尋找execspawn 請參閱相關的API文檔 文檔中有兩個命令的示例。

execspawn

execspawn的“簡單”版本。 前者使用單個回調在命令完成時向用戶報告,並且僅在完成/失敗時報告。

child = exec('cat *.js bad_file | wc -l',
  function (error, stdout, stderr) {
    console.log('stdout: ' + stdout);
    console.log('stderr: ' + stderr);
    if (error !== null) {
      console.log('exec error: ' + error);
    }
});

所以基本上提供的回調函數只調用,當被寫入標准輸出/標准錯誤可用, 完全 在進程終止(成功或失敗)之后,才會調用回調,用戶(您)可以對其進行操作。 如果它失敗了error真的

spawn是不同的,因為你可以監聽stdout / stderr 事件 首先,你“產生”一個過程。 spawn函數返回對子進程的引用。

var spawn = require('child_process').spawn;
var ls = spawn('ls', ['-lh', '/usr']);

ls這里是你已經催生子進程。 它有兩個屬性(現在很重要), stdoutstderr是事件發射器。 他們正在發布data事件。 當它寫在任一流上的東西時,會調用在data事件上注冊的回調。

ls.stdout.on('data', function (data) {
  console.log('stdout: ' + data);
});

ls.stderr.on('data', function (data) {
  console.log('stderr: ' + data);
});

當然還有其他重要事件(當然,請查看最新和相關信息的文檔)。

ls.on('close', function (code) {
  console.log('child process exited with code ' + code);
});

當你想要在stdout上捕獲東西時,你會使用spawn ,例如在進程運行時。 一個很好的例子是,如果你產生一個ffmpeg編碼任務,需要幾分鍾才能完成。 你可以在stderr上監聽(因為ffmpeg將進度信息寫入stderr而不是stdout)來解析“進度”信息。

carrier逐行

有一個很好的額外庫,你可以與spawn一起使用。 它被稱為載體 它有助於從生成的進程的stdout / stderr中讀取“行”。 它很有用,因為傳遞給回調的data參數不一定包含由\\n分隔的“完整”行。 carrier幫忙。 (但是,它不會幫助你捕獲ffmpeg在stderr上的進度,因為在這種情況下沒有ffmpeg寫的換行符,它只是一個回車符,這行總是基本重寫。)

你會像這樣使用它

var carry = require("carrier").carry;
var child = spawn("command");   
carry(child.stdout, function(line) {
   console.log("stdout", line);
});

承諾和延期

如果您想使用promise / deferred樣式方法,那么您可以使用AngularJS 使用的Q來執行類似下面的操作 - 或者至少非常相似(請參閱有關promises的完整教程的鏈接)。

spawn返回一個不是promise的Emitter對象。 因此,您必須將調用包裝為spawn( 請參閱使用Deferreds )。

var q = require("q");
var spawn = require("child_process").spawn;

var ls = function() {
  var deferred = q.defer();
  var ls = spawn("ls", ["-lh", "/usr"]);
  ls.stdout.on("data", function(data) {
    deferred.notify({stdout: true, data: data});
  });
  ls.stderr.on("data", function(data) {
    deferred.notify({stderr: true, data: data});
  });
  ls.on("close", function(code) {
    if (code === 0) {
      deferred.resolve();
    } else {
      deferred.reject(code);
    }
  });
  return deferred.promise;
};

通過執行ls()現在返回一個promise,你將像任何其他promise一樣使用它。 當它完全解決后,將調用第一個回調。 如果發生錯誤(該過程存在非零退出代碼),則調用錯誤處理程序。 當命令進行時,將調用第三個回調(通知回調)。

ls().then(function() {
  console.log("child process exited successfully");
}, function(err) {
  console.log("child process exited with code " + err);
}, function(args) {
  if (args.stdout) {
    console.log("stdout: " + args.data);
  } else {
    console.log("stderr: " + args.data);
  }
});

當某些東西寫入stderr時你可以立即調用拒絕,但這是一個設計決定。 回到ffmpeg示例,這對你沒有任何好處,因為ffmpeg將一般信息吐出到stderr。 但是它可以與其他命令一起使用。

我想你會得到它:)

示例來自nodejs的文檔,因為它們很好理解。

在核心節點庫中,同步函數將Sync附加到函數名稱。 他們正在使用child_process.execFileSync ,因此您應該為該函數的異步版本尋找child_process.execFile

我推薦一種結合發電機和承諾的方法。 以下是先決條件:

然后做你想要的那種事情:

var co = require('co');
var adapt = require('ugly-adapter');
var childProcessExec = require('child_process').exec;
var exec = adapt.part(childProcessExec);

co(function*() {

  // run commands in parallel by yielding
  // a single object or array
  var result = yield {
    listing: exec('ls -l'),
    mkdirResult: exec('mkdir foo'),
    blah: exec('echo "blah blah"'),
  };

  console.log(result.blah); // "blah blah"

  // run commands in series by yielding
  // one thing at a time
  var listing = yield exec('ls -l');
  var mkdirResult = yield exec('mkdir foo2');
  var blah = yield exec('echo "blah blah"');

  console.log(blah); // "blah blah"

}).catch(function(err){

  // this handles any possible errors
  // thrown by the above
  console.error(err.stack);
  process.exit(1);
});

yield關鍵字使函數暫停,同時co展開promise並將結果發送回函數。 注意:co實際上只是async / await的一個臨時替代,它在es7中出現並且工作方式基本相同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM