你好,长话短说:我正在尝试创建一个脚本,通过 CI 服务器运行来终止特定的进程。
因此通过互联网搜索我发现了这个命令:
myuser@server:/home/myuser# ps -ef | grep someUniqueText | grep -v grep | awk '{print $2}'
5263
当我在控制台中运行它时,它返回我所需要的内容(5263
),所以我创建了这个 bash:
#!/bin/bash
PROCESSNAME=$1
PID=$(ps -ef | grep $PROCESSNAME | grep -v grep | awk '{print $2}');
echo $PID;
当我按如下方式执行它时:
myuser@server:/home/myuser# ./killProcess.sh somename
5263 4587 1236
bash 脚本返回 3 个数字,第一个是我需要的进程,我不知道另外两个是什么,为什么?oO
PS:我echo
先用来测试一下,以后我会改成kill -9
答案1
运行时./killProcess.sh somename
,类似于
/bin/bash ./killProcess.sh somename
存在,并且ps | grep | grep | awk
-line 也找到了这个,因为它包含文本somename
。我不太清楚为什么你会得到两个额外的 PID(而不仅仅是一个),但我认为这是bash
和之间的一些父/子关系killProcess.sh
。在一行中,PID 显示为 PID,在另一行中显示为 PPID。
您可以通过根据脚本名称 grep 来避免这些 PID。它存储在 中$0
,因此
PID=$(ps -ef | grep $PROCESSNAME | grep -v grep | grep -v $0 | awk '{print $2}');
或(使用更少的程序调用):
PID=$(ps -ef | grep $PROCESSNAME | grep -v -e grep -e $0 | awk '{print $2}');
另一种(更安全)的方法是 grep 掉脚本的 PID。它存储在$$
:
PID=$(ps -ef | grep $PROCESSNAME | grep -v -e grep -e $$ | awk '{print $2}');
或者全部执行awk
:
PID=$(ps -ef | awk "/$PROCESSNAME/ && !/awk/ && !/$$/ {print \$2}");
我们需要\$2
在此处转义,以便它不被 shell 解释,而是由 解释awk
。该命令的意思是:
如果该行包含$PROCESSNAME
且不awk
包含我们自己的 PID,则打印第二列。
优点是(理论上)运行速度更快,因为只awk
需要一个附加命令(),而不是 3 个 greps 和一个 awk。
但:
所有这些greps和awks并不完美,你总会发现我们没有想到的情况(例如部分匹配等)。因此,我建议使用已经写好的工具之一:
killall somename
# 预览,首次运行killall -v -s 0 somename
pgrep somename
# 仅列出 PIDpkill somename
# 如同killall
答案2
我曾经实现过类似的想法,作为一个 shell 函数,我称之为psg
(“ps|grep”)
psg() {
local -a patterns=()
(( $# == 0 )) && set -- $USER
for arg do
patterns+=( "-e" "[${arg:0:1}]${arg:1}" )
done
ps -ef | grep "${patterns[@]}"
}
这使用了一个技巧,将模式的第一个字符放在括号中,这样你就可以得到
ps -ef | grep "[s]omename"
这使您可以删除grep -v grep
管道的一部分。
如果您不传递任何参数,它会使用您的用户名来搜索您的进程。