2012-09-02 60 views
4

我正在編寫一個腳本來殺死同一進程的所有實例。由於它將用於Linux,AIX,HP-UX和Solaris,我只需要使用內置的bash(sh)函數。這就是爲什麼killallpkill等不適合我。計算進程數並殺死它們

一旦只有一個,應該在傳統的方式剛剛殺了一個過程的實例:

kill -TERM `ps -ef | grep -v grep | grep $process | awk '{print $2}'` 

但是有時候程序額外的實例上運行,這就是爲什麼ps -ef | …回報比一個PID多。這需要報告。

例如:

bash-3.2$ ps -ef | grep -v grep | grep perl | awk '{print $2}' 
5267 
5268 
5269 
5270 
5271 

我的想法是爲這些值存儲在臨時變量,然後發送終止信號,以各自在for循環。

bash-3.2$ tmp=`ps -ef | grep -v grep | grep perl | awk '{print $2}'` 
bash-3.2$ echo $tmp 
5267 5268 5269 5270 5271 

但是,如果發生這樣的情況(有多少實例存在),我仍然需要這些信息。 看來我需要檢查存儲在tmp變量中的整個字符串,並可能計數空格嗎?

無論如何,這些問題會減少到如何檢查$tmp變量存儲多少個值?

+0

你可以只用一個計數器在循環告訴你如家快捷很多特效被打死。 – John3136

+0

'ps -ef'是否便攜? –

+0

@glennjackman [是](http://pubs.opengroup.org/onlinepubs/7990989775/xcu/ps.html)(但在當前POSIX + OpenGroup規範中標記爲XSI)。 – Gilles

回答

3

爲了獲得最大的portability和可靠性,使用-A(的-e POSIX代名詞)以及使用-o而不是-f的自定義格式。

您對ps輸出的過濾很脆弱:它可能與其他進程匹配。您必須排除grep進程,並且您可能還需要排除腳本,並且可能還有其他完全無辜的進程(例如您的腳本本身)被捕獲,因爲它們的命令行碰巧包含$process作爲子。儘可能嚴格地進行過濾。使用ps -o pid= -o comm=時,您只會得到兩列(沒有參數的PID和命令),而沒有標題。

您不需要使用循環來執行查殺,kill接受多個參數。爲了進行計數,讓shell執行此操作:使用空格分隔的數字列表,讓shell執行分詞(使用$(…)外部引號)並計算結果字數($#)。

count_and_kill_processes() { 
    set -- $(ps -A -o pid= -o comm= | 
      awk -v "name=$process" '$2 == name {print $1}') 
    count=$# 
    if [ $# -ne 0 ]; then kill "[email protected]"; fi 
} 
count_and_kill_processes foo 
# now the number of killed processes is in $count 

如果你的shell在所有機器上都是bash或ksh,你可以使用一個數組。

pids=($(ps -A -o pid= -o comm= | 
      awk -v "name=$process" '$2 == name {print $1}')) 
if [[ $# -ne 0 ]]; then kill "[email protected]"; fi 
# the number of killed processes is ${#pids} 
1

您可以使用一個循環應在這兩種情況下工作:

for pid in $(ps -ef | grep -v grep | grep $process | awk '{print $2}'); do 
    echo $pid 
done 

或計數的匹配數量:

if [ $(ps -ef | grep -v grep | grep $process | awk '{print $2}' | wc -l) -gt 1 ] 
then 
    # more than one 
fi 
2

使用xargs的:

ps aux | grep -ie perl | awk '{print $2}' | xargs kill -9