Shell
為什麼我的孤兒孫子只有產出產出才會死?
我傾向於一個程序“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 似乎是預設的reaper。
pstree
看起來像這樣:systemd─┬─java───sh───slave └─slave
在功能上,我通過明確殺死奴隸的整個家庭來解決這個問題。然而我仍然想知道:
為什麼 systemd 只有在寫入標準輸出(或錯誤)並且只有在標準輸出之前被另一個程序讀取時才會殺死孤兒?
這個問題相當冗長。根據要求,我可以提供一個最小的程式碼範例來重現所描述的行為。
這可能不是 systemd 這樣做的。
相反,當程序嘗試寫入讀取端已關閉的管道時,程序會被 SIGPIPE 殺死——這符合“標準輸出之前已被另一個程序讀取”的描述。