2012-09-02 64 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