Shell

為什麼我的孤兒孫子只有產出產出才會死?

  • November 30, 2021

我傾向於一個程序“master”,它管理一組同時執行的子程序“slave”。根據需要啟動和終止子流程。許多這些子流程使用啟動腳本。

輸出pstree看起來像這樣(摘錄,master 是用 Java 實現的,兩個 slave 是通過腳本啟動的):

systemd───java─┬─sh───slave
              ├─slave
              └─sh───slave

以前,啟動腳本將奴隸的輸出重定向到日誌文件。決定主機也應該處理從機的輸出。通過添加這樣的緩衝讀取器來擴展 master 的實現:

process =  Runtime.getRuntime().exec(cmd);
BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
while (null != (line = br.readLine())) {
   // handle slave output here
}

然後系統對已被SIGTERM主人殺死(發送)但實際上仍在執行的奴隸產生了嚴重的問題。我注意到這只發生滿足兩個標準的奴隸身上:

  • 他們使用了啟動腳本
  • 他們很少寫到標準輸出

由於 master 沒有殺死 slave,而只是殺死了它的直接父級(shell 解釋器),所以 slave 現在歸 init 所有。就我而言, systemd 似乎是預設的reaperpstree看起來像這樣:

systemd─┬─java───sh───slave
       └─slave

在功能上,我通過明確殺死奴隸的整個家庭來解決這個問題。然而我仍然想知道:

為什麼 systemd 只有在寫入標準輸出(或錯誤)並且只有在標準輸出之前被另一個程序讀取時才會殺死孤兒?

這個問題相當冗長。根據要求,我可以提供一個最小的程式碼範例來重現所描述的行為。

這可能不是 systemd 這樣做的。

相反,當程序嘗試寫入讀取端已關閉的管道時,程序會被 SIGPIPE 殺死——這符合“標準輸出之前已被另一個程序讀取”的描述。

引用自:https://unix.stackexchange.com/questions/679303