国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

使用node子進程spawn,exec踩過的坑

cppprimer / 3810人閱讀

摘要:最后發現使用子進程打開還真的就是使用到一定程度就掛掉。上面的簡單流程就是啟動一個子進程。邏輯就是,記錄子進程的大小,一旦超過就掉子進程。我們在使用時,不知道設置,默認的是當我們子進程日志達到時,自動掉了。

如何在項目中實現熱更新中提到的一個坑child_process的exec使用問題,下面文章會詳細介紹下,debug到node源碼中的詳細介紹,不容錯過。

child_process介紹

Nodejs是單線程單進程的,但是有了child_process模塊,可以在程序中直接創建子進程,并使用主進程和子進程之間實現通信。

對于child_process的使用,大家可以找找其他文章,介紹還是比較多的,本文主要講一下踩過的坑。

踩過的坑

在使用EHU(esl-hot-update)這個工具時(對于工具的介紹,參考前面的文章如何在項目中實現熱更新),發現用子進程啟動項目,經常性的掛掉。然后也不知道為什么,甚至懷疑子進程的效率比較低。

最后為了進一步驗證,在同樣的環境下,一個直接啟動服務,一個是使用require("child_process").exec("...") 方式啟動。

最后發現使用子進程打開還真的就是使用到一定程度就掛掉。雖然此時也沒有什么解決方案,但是至少能把問題定位在子進程上了,而不是其他工具代碼導致程序掛掉。

定位問題

定位了問題后,網上查找child_process相關資料,發現exec與spawn方法的區別與陷阱 這篇文章提到幾點:

exec與spawn是有區別的

exec是對spawn的一個封裝

最重要的exec比spawn多了一些默認的option

基于以上幾點有些頭緒了,但是還是沒有明確的解決方案。

最后一個辦法,直接斷點到nodejs的child_process.js模塊中嘗試看看問題出在哪里。

exec和spawn的源碼區分

斷點進去看后,豁然開朗,exec是對execFile的封裝,execFile又是對spawn 的封裝。

每一層封裝都是加強一些易用性以及功能。

直接看源碼:

exports.exec = 
    function(command /*, options, callback*/) {
          var opts = normalizeExecArgs.apply(null, arguments);
          return exports.execFile(opts.file,
                                  opts.args,
                                  opts.options,
                                  opts.callback);
};

exec對于execFile的封裝是進行參數處理

處理的函數:

normalizeExecArgs

關鍵邏輯

if (process.platform === "win32") {
    file = process.env.comspec || "cmd.exe";
    args = ["/s", "/c", """ + command + """];
    // Make a shallow copy before patching so we don"t clobber the user"s
    // options object.
    options = util._extend({}, options);
    options.windowsVerbatimArguments = true;
  } else {
    file = "/bin/sh";
    args = ["-c", command];
  }

將簡單的command命名做一個,win和linux的平臺處理。

此時execFile接受到的就是一個區分平臺的command參數。

然后重點來了,繼續debug,execFile中:

var options = {
    encoding: "utf8",
    timeout: 0,
    maxBuffer: 200 * 1024,
    killSignal: "SIGTERM",
    cwd: null,
    env: null
};

有這么一段,設置了默認的參數。然后后面又是一些參數處理,最后調用spawn方法啟動子進程。

上面的簡單流程就是啟動一個子進程。到這里都沒有什么問題。

繼續看,重點又來了:

用過子進程應該知道這個child.stderr

下面的代碼就解答了為什么子進程會掛掉。

child.stderr.addListener("data", function(chunk) {
    stderrLen += chunk.length;

    if (stderrLen > options.maxBuffer) {
      ex = new Error("stderr maxBuffer exceeded.");
      kill();
    } else {
      if (!encoding)
        _stderr.push(chunk);
      else
        _stderr += chunk;
    }
});

邏輯就是,記錄子進程的log大小,一旦超過maxBufferkill掉子進程。

原來真相在這里。我們在使用exec時,不知道設置maxBuffer,默認的maxBuffer是200K,當我們子進程日志達到200K時,自動kill()掉了。

exec和spawn的使用區分

不過exec確實比spawn在使用上面要好很多

例如我們執行一個命令

使用exec

require("child_process").exec("edp webserver start");

使用spawn

linux下這么搞

var child = require("child_process").spawn(
   "/bin/sh", 
   ["-c","edp webserver start"],
   {
       cwd: null,
       env: null,
       windowsVerbatimArguments: false
   }
);

win下

var child = require("child_process").spawn(
   "cmd.exe",
   ["/s", "/c", "edp webserver start"],
   {
       cwd: null,
       env: null,
       windowsVerbatimArguments: true
   }
);

可見spawn還是比較麻煩的。

解決方案

知道上面原因了,解決方案就有幾個了:

子進程的系統,不再輸出日志

maxBuffer這個傳一個足夠大的參數

直接使用spawn,放棄使用exec

我覺得最優的方案是直接使用spawn,解除maxBuffer的限制。但是實際處理中,發現直接考出normalizeExecArgs這個方法去處理平臺問題,在win下還是有些不好用,mac下沒有問題。所以暫時將maxBuffer設置了一個極大值,保證大家的正常使用。然后后續在優化成spawn方法。

吐槽

其實沒有怎么理解,execFile對于spawn封裝加maxBuffer的這個邏輯,而且感覺就算加了,是否也可以給一個方式,去掉maxBuffer的限制。

難道是子進程的log量會影響性能?

感想

其實在解決這個問題時,發現這個差異/坑還比較意外,因為自身對于node其實還不是很熟,這個子進程的使用其實也是在ehu中第一次遇到。

感受比較多的就是有時候正對問題去學習/研究,其實效率特別高。

微信公眾號

博客地址

http://tangguangyao.github.io/

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/78332.html

相關文章

  • 記錄我開發gpm,Git倉庫管理工具的歷程

    摘要:前言記錄下開發的一些事,加強自己對的應用。雛形參考于的項目管理,發現非常的優雅。嘗試通過修改權限為,最后無果不了了之。方式二詢問篩選會在終端監聽輸入的關鍵字,根據關鍵字篩選出一系列的倉庫。自己也在使用,打算長期維護。 前言 記錄下開發的一些事,加強自己對nodejs的應用。共勉! 有讓你操蛋的事,就有需求 對于經常參與開源貢獻,或者看見某些庫,像試試手的人來說,經常需要git clon...

    thursday 評論0 收藏0
  • Node.js中spawnexec的異同比較

    摘要:返回值對象利用給定的命令以及參數執行一個新的進程,如果沒有參數數組,那么將默認是一個空數組。當子進程執行完畢后將會執行的回調函數,參數有返回值對象在中運行一個命令,并緩存命令的輸出。 前言 眾所周知,Node.js在child_process模塊中提供了spawn和exec這兩個方法,用來開啟子進程執行指定程序。這兩個方法雖然目的一樣,但是既然Node.js為我們提供了兩個方法,那它...

    garfileo 評論0 收藏0
  • nodeJS多進程

    摘要:通過將的給出來的進程。恩吞吐率關于吞吐率有多種解讀,一種是描繪服務器單位時間處理請求的能力。而根據這個描述的話他的單位就為而這個指標就是上面數據中的當然,肯定是越大越好了吞吐量這個和上面的吞吐率很有點關系的。 首先鄭重聲明:nodeJS 是一門單線程!異步!非阻塞語言!nodeJS 是一門單線程!異步!非阻塞語言!nodeJS 是一門單線程!異步!非阻塞語言! 重要的事情說3遍。 因為...

    happen 評論0 收藏0
  • nodeJS多進程

    摘要:通過將的給出來的進程。恩吞吐率關于吞吐率有多種解讀,一種是描繪服務器單位時間處理請求的能力。而根據這個描述的話他的單位就為而這個指標就是上面數據中的當然,肯定是越大越好了吞吐量這個和上面的吞吐率很有點關系的。 首先鄭重聲明:nodeJS 是一門單線程!異步!非阻塞語言!nodeJS 是一門單線程!異步!非阻塞語言!nodeJS 是一門單線程!異步!非阻塞語言! 重要的事情說3遍。 因為...

    james 評論0 收藏0
  • Node.js child_process模塊解讀

    摘要:而且方式創建的子進程與父進程之間建立了通信管道,因此子進程和父進程之間可以通過的方式發送消息。與事件的回調函數有兩個參數和,代碼子進程最終的退出碼,如果子進程是由于接收到信號終止的話,會記錄子進程接受的值。 在介紹child_process模塊之前,先來看一個下面的代碼。 const http = require(http); const longComputation = () =>...

    baiy 評論0 收藏0

發表評論

0條評論

cppprimer

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<