這個問題的完整標題是:
Bash:當 control-c 無法殺死進程時該怎麼辦,因為 bash 腳本包含一個呼叫另一個進程的循環:對於開/關電源按鈕是否有更好的解決方案?
這個問題的標題是相當不言自明的,但這裡有一些更詳細的資訊:
我正在運行一個 bash 腳本,它調用另一個程式。 (運行/執行另一個程式。)
該程序是數據/曲線擬合程序,不能用 中斷CTRL-C
。但是,從讀到這篇文章郵政,我發現我可以殺死它CTRL-\
假設性想法...
所以可以直接敲擊鍵盤,按住 CTRL 鍵,然後敲擊按鍵\
,但如果你昨天買了一個非常昂貴的機械鍵盤,但沒有足夠的錢去購買另一個你願意「混搭」的便宜鍵盤,該怎麼辦(因為你不想用完這 10^6 個按鍵中的任何一個)在你閃亮的新機械鍵盤磨損之前擁有),或者沒有足夠的時間在你的房子裡找到你的舊鍵盤,因為你的房子要么極為混亂(一團糟)或因為同時發生諸如晶片盤火災之類的緊急情況...
還要考慮到一個循環正在調用這個擬合程序,也許您正在擬合 1000 個數據文件,按該\
鍵 1000 次可能會花費很長時間。
超空間思維...
甚至;如果您在 bash 腳本中犯了一個錯誤並且它實際上正在執行無限循環怎麼辦?
在這種情況下,您可以採取什麼措施來停止父腳本的執行?您可以拔掉電腦的插頭,按住電源按鈕 10 秒鐘將其關閉,或者將其扔進晶片盤火中以停止其工作,但由於可能會發生資料遺失,這些解決方案似乎不明智。
理論上,我們可以運行系統監視器,也許還可以退出bash 進程,但是如果您有許多同名的此類進程,這可能很難找到...此外,您可能有一台單核計算機,或者一台具有 N 個核心的多核心計算機,運行 N 個進程,這些進程都試圖使用 100% CPU。或者也許只有 1 個進程使用的內存超過了您擁有的 4 GB 內存,因此您的計算機速度非常慢……至少目前無法運行系統監視器。此後的下一個最佳選擇是按 CTRL-ALT-F1 並嘗試以 root 身份登入並使用ps -A
then找到有問題的 bash 父級kill PID
...但是,如果您的電腦負載如此之重,這可能會花費您幾分鐘的時間它正在不斷地寫入以進行交換。
SIG TERM exec cpu_broken.sh;重新召集;清晰的螢幕;清晰的思考過程;繼續...
有更好的解決方案嗎?
答案1
因此,基本上,您運行的腳本使所有內容都無法訪問,並且您需要快速且簡單的解決方案來阻止它。重新啟動電源的另一種方法是按住SYSRQ鍵(在許多情況下與 鍵相同PRTSC),然後一一按下R, E, I, S, U, B。基本上,這是終止所有正在運行的進程並重新啟動系統的安全方法。
替代方法是sudo nano /proc/sysrq-trigger
在該文件中寫入 b , 並保存。系統將立即重新啟動
答案2
您需要殺死整個進程組。進程組 ID (PGID) 是啟動該群組的進程的 PID。要終止進程組,您需要找到啟動該進程組的進程的 PID,即啟動該進程組的腳本或命令。語法是:
kill -- -PGID
例如:
kill -- -1234
這裡1234是PGID(進程組ID)。
這會將 SIGTERM 傳送到進程組中的所有進程。若要傳送不同的訊號,例如 SIGKILL (9),請執行以下操作:
kill -9 -1234
如何查找 PGID:
你可以做:
ps -eo 'pid,ppid,pgid,cmd'
這將顯示 PID、PPID(父進程 ID)、PGID 和進程名稱。
現在您可以使用grep
或任何其他合適的方法找到PGID,然後透過上述方法殺死它。
我使用命令來顯示 PPID 的原因是因為您也可以嘗試透過以下方式終止基於 PPID 匹配的進程pkill
:
pkill -P PPID
例如:
pkill -P 6789
使用這種方法,您需要找到所有父進程(和子進程),然後殺死它們,所以在我看來,如果您想殺死所有進程樹,則殺死整個進程樹是更好的方法。
答案3
通常您可以使用top
,htop
或類似的命令來查找進程並殺死它(或者如果您知道進程的名稱或 PID,則可以killall
等pkill
)。例如,使用top
,我可以選擇從終端運行的腳本並按k+終止它Enter:
如果這不起作用,k++9應該Enter使用 SIGKILL 訊號。 SIGKILL 請求立即終止進程,而不是像 SIGTERM 那樣等待進程完成清理資源等操作。Ctrl+C進程僅發送 SIGINT 來中斷進程,就像 SIGTERM 一樣。
使用 htop 中的樹狀視圖(按t)也表示您可以確定腳本的父進程,並終止它們以確保它不會繼續循環。
也可以看看:
- Unix 訊號:POSIX 訊號 - 維基百科
- UNIX 手冊頁:訊號 (7)(取得已安裝的版本運行
man 7 signal
)