Ubuntu

自定義“垃圾收集器”以手動關閉程序

  • December 23, 2016

我正在執行 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 秒。

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