更優雅的 kill 進程
使用 unix 的時候常常需要 kill 一個進程,而我們又常常記不住進程的 pid,所有一般首先使用 ps 命令來打印系統中的進程,然後對 ps 得到的數據以進程名進行過濾,提取出相對應的 pid,以該 pid 爲參數調用 kill 就完成了整個的任務。
一個基礎的示例如下:
-
查找進程
[longyu@debian:18:12:14] ~ $ ps -ef | grep bash
longyu 7175 1964 0 18:05 pts/0 00:00:00 /bin/bash
longyu 8313 7175 0 18:12 pts/0 00:00:00 grep --color=auto bash -
kill 進程
kill -9 7175
-9 制定 kill 強制終止進程,這在某種情況下可能會造成問題,常常是進程所佔有的某些資源沒有正常釋放的問題。可以使用 kill 的默認發送信號,SIGTERM 來讓進程正常終止。
《APUE》 中對 SIGTERM 信號的講解內容如下:
這是 kill 命令在默認情況下發送的終止信號。因爲它可以被應用程序捕捉到,因此使用 SIGTERM 能夠給應用程序一個在 exit 之前執行回收工作優雅終止的機會(與 SIGKILL 正相反, SIGKILL 不能被捕捉到或忽略)。
一個可以判定爲存在問題的更高級的示例如下:
1. kill $(ps -ef | grep top | awk '/ top$/ {print $2}')
bash: kill: (10793) - No such process
2. ps -ef | grep top | awk '/ top$/ {print $2}' | xargs kill
上面的第一個命令執行時,子 shell 創建的 grep 命令也將會被找到,子 shell 執行完後 grep 命令的主體進程已經終止,pid 已經無效,因此會有上面的錯誤。
第二個命令執行時,grep 命令的執行進程也會被找到,只是在發送 kill 信號的時候,該進程還沒有終止,因此不會報第一個命令中的錯誤。
一個改進的示例如下:
kill $(ps -ef | grep top | grep -v grep | awk '/ top$/ {print $2}')
上述命令能夠解決 grep 中找到子 shell 中 grep 命令主體進程的問題,但上述方式的執行效率較低。
一個更好的示例如下:
ps -ef | awk '/ top$/ {print $2}' | xargs kill
kill $(ps -ef | awk '/ top$/ {print $2}')
使用 awk 來代替 grep,不僅沒有前幾個示例中存在的問題,也減少了進程的使用數目,減少了管道的使用數目,有很好的性能。
也可以使用 sed 來代替 awk,不過在這種方式下,sed 中的匹配字符串不容易寫出來,你需要使用匹配子串來完成,對於這個簡單的任務來講,你直接使用 awk 就可以了。