自定義“垃圾收集器”以手動關閉程序
我正在執行 Ubuntu 16.04
我有這個程序 X 從多個 tty 執行。我使用 screen 命令從其他偽終端執行它,它也從 crontab 執行。
這個程序是從一個從 bash 腳本啟動的 python 腳本啟動的。
有時,python 腳本會遇到一個我無法捕捉到的異常,它會讓這個程序 X 繼續執行。
我想在 bash 腳本的末尾殺死這個程序 X,但要避免殺死從其他終端執行的其他 X 程序。
我想使用 -t 參數執行 pgrep 來處理與其他終端無關的 X,但我無法理解文件中的語法。
為 Python 程式碼(使用該
setsid
實用程序)和它啟動的任何其他程序(包括應用程序本身)啟動一個新程序組,因此您可以在需要時終止整個程序組。您可以使用以下構造來執行此操作:
exec 3>&1 pgid=$(exec setsid bash -c 'echo $$; exec >&3-; exec COMMAND...')
COMMAND...
您通常啟動的命令及其參數在哪裡。請注意,它在單引號內,並且要執行的命令必須可以作為字元串進行評估(與普通的 shell 表達式相反)。第一個重定向
3>&1
將標準輸出描述符複製到描述符 3。重定向>&3-
將描述符 3 移動到標準輸出。
$(...)
執行...
, 並評估它寫入標準輸出的數據。上面,我們將標準輸出讀入 shell 變數pgid
。子shell (
...
) 被替換為setsid
實用程序,該實用程序在新會話(程序組)中執行其參數。在這裡,它執行bash
,列印出目前程序 PID ($$
),將原始標準輸出從描述符 3 移回,並替換自身/執行所需的COMMAND...
.只要
COMMAND...
執行,shell 就會執行該行,並且只會在COMMAND...
自身退出後繼續執行下一行。如果
COMMAND...
留下虛假程序在執行,並且您想殺死它們,您需要做的就是執行kill -SIGNAL -$pgid
問題是發送哪個信號。
KILL
會立即殺死程序組中剩餘的程序,所以是最簡單的選擇。但是,如果程序表現良好,您應該能夠通過向它們發送信號來要求它們退出。TERM
當然,有時程序可能會處於不穩定狀態,因此它們不會做出反應TERM
並且確實需要進行KILL
編輯。要解決這個問題,您可以使用一個小循環,並ps
查看是否還有任何程序:retries=50 while ((1)); do # Processes left? left=$(ps -o pid= -s $pgrp) [ -n "$left" ] || break # Ask them to terminate. kill -TERM $left # Wait 0.1 seconds. sleep .1 # Decrement the retry counter. ((--retries > 0)) || break done # If there are any processes left in the group, # send them a KILL signal. left=$(ps -o pid= -s $pgrp) [ -n "$left" ] && kill -KILL $left
請注意,50 次重試(每次 0.1 秒)意味著在發送終止信號之前最多只等待 5 秒。這可能不是一個合適的值,具體取決於應用程序及其執行的硬體類型。例如,如果機器是筆記型電腦,並且應用程序保存了一些歷史記錄或登錄到許多文件中,並且驅動器恰好在退出點處於休眠狀態,那麼我會將延遲提高到 15 到 30 秒。