如何杀死除一个进程之外的所有进程,除非有一个进程

如何杀死除一个进程之外的所有进程,除非有一个进程

我有一个这样的脚本:

pid = $(ps -ef | grep my-service | awk '{print $2}')

这给了我正在运行的进程的 PID my-service。我想更新我的脚本以处理正在运行的多个进程,并杀死my-service除最新进程之外的所有旧进程。但如果只有一个进程在运行,则将其杀死。我怎么做?

答案1

pgrep( 和pkill) 有一些对此任务有用的参数,例如-c( --count) 用于计算进程数,-n( --newest) 用于仅获取最新的 pid。 (man pgrep了解更多)

所以我们可以使用这个case声明。如果没有返回 pid,我们就退出,如果有,我们就终止这个进程。如果发现多个进程,我们会针对grep -v所有 pid 排除最新的 pid,然后通过管道传输到kill.

#!/bin/bash

die="my-service"

case $(pgrep -cf "$die") in
    0) exit 0 ;;
    1) pkill -f "$die" ;;
    *) grep -v $(pgrep -nf "$die") <(pgrep -f "$die") | xargs kill ;;
esac

注意:上面-f使用了参数,这是匹配完整的命令,如果我们只想匹配进程名称,则不应该使用它。从man pgrep

-f,--完整

该模式通常仅与进程名称匹配。设置 -f 时,将使用完整命令行。

答案2

假设 procps-ngps和未修改的$IFS,你可以这样做:

set -- $(ps -o pid= --sort=-start_time -C my-service)
case $# in
  (0) ;;
  (1) kill "$1";;
  (*) shift; kill "$@"
esac

set分配位置参数( $1, $2...) 到名称为 的进程的 pid my-service,按start_time(最近启动的最先)反向排序。

然后根据它们的编号($#),如果为 0,我们不执行任何操作,如果为 1,则杀死它,对于任何其他数字,shift丢弃最小的,并杀死其余的。

(注意ps -C name匹配确切地在完整的进程名称上,而不是在 报告的 arg 列表上ps -f

相关内容