我啟動了一個無法運行的應用程序,但無法刪除它,因為它仍在運行。我可以列印 PID,但不能殺死使用它的進程。
~ $ ps ax | grep snappr | awk '{print $1}'
70824
~ $ kill $(ps ax | grep snappr | awk '{print $1}')
-bash: kill: (70832) - No such process
答案1
您是否注意到兩次嘗試中獲得了兩個不同的 PID?
考慮一下:如果您鍵入類似 的命令vi raven.txt
,ps ax
則會顯示一行顯示 的命令vi raven.txt
。同樣,如果您鍵入類似 的命令grep snappr
,ps ax
則會顯示一行顯示 的命令grep snappr
。並且,如果您ps
透過管道輸出該輸出grep snappr
,grep
則會找到該行那是在描述自己。所以,如果你輸入
$ ps ax | grep snappr | awk '{print $1}'
重複地,它每次都會列印不同的數字(因為它會列印 的 PID ,並且每次執行命令時grep
都會得到一個新的、唯一的進程)。grep
最後,請考慮:kill
在知道其參數之前,無法執行該命令。要了解其參數,$(ps ax | grep snappr | awk '{print $1}')
管道必須已完成。這意味著1grep
必須已終止。因此,只有在該進程終止後才會給出該進程的 PID——因此,它自然會報告「沒有這樣的進程」。kill
grep
grep
也許我應該提到沒有snappr
進程正在運行。如果有,您的第一個指令將輸出兩個數字: 的 PIDsnappr
和 的 PID grep snappr
。現在,如果snappr
正在運行,您的命令可能會開始半正確地運行,我的意思是它會執行您想要的操作,但也會給出錯誤訊息。如果snappr
以 PID 42097 運行,並grep snappr
以 PID 70848 運行,則kill
命令將為kill 42097 70858
,這將殺死snappr
並在嘗試終止grep
不再存在的進程時收到錯誤訊息。
您可能想要改進這一點。我最喜歡的方法是我 20 年前發明的,它將更改為grep
,grep "[s]nappr"
它會匹配snappr
但不會匹配自身。另一種方法是使用pgrep
而不是ps | grep
.
1或者,awk
如果grep
僅關閉其標準輸出,則可以完成。對於 *nix 程式來說,這是非常不尋常的行為。
答案2
簡短的答案
不要跳過 Bash 的圈子來用snappr
、ps
管道通過grep
然後通過awk
這樣的管道來殺死。相反,嘗試使用這樣的方式殺死它pkill
;沒有混亂或大驚小怪,它的目標是基於開箱即用的進程名稱:
sudo pkill snappr
更長的答案
不太清楚如何鯛魚在系統進程層級上運行,但問題可能是您僅取得子進程 ID 而不是父進程 ID。
事實上,我相信您用來獲取進程 ID 的方法 ( ps ax | grep snappr | awk '{print $1}'
) 將返回所連接的進程 ID 的完整列表,snappr
無論它是父進程還是子進程。所以用你可能殺死一個只是子進程 ID 的進程 ID,但父 ID 仍然處於活動狀態,並且能夠「產生」另一個子進程來進行補償。
因此,也許您可以執行類似的操作來獲取您提供的任何進程 ID 的最終父 ID,並對其執行操作;其工作原理的簡單概念證明:
ps -p [process ID] -o ppid=
在 Bash 中執行該裸命令將為您提供您輸入的子進程 ID 的父進程 ID [process ID]
。因此,如果子 ID4567
有一個父進程 ID,123
那麼命令將是:
ps -p 4567 -o ppid=
那將會返回,123
。
也就是說,這可能是處理雜散進程的一種危險方法,因為如果您的腳本獲取 的實際父進程 ID snapper
,那麼該進程 ID 的父進程實際上可能是您自己的 Bash shell。因此,您可能會無意中殺死您的 Bash shell,而不是讓snapper
您離開系統,同時讓snapper
進程保持運作。
但話雖如此,為什麼不讓你的生活變得更輕鬆,直接跑步呢pkill
像這樣:
sudo pkill snappr
這將殺死所有連接到的進程,而snappr
無需任何花哨的命令列操作。