pgrep的一次入坑经历

起因

公司项目十多年前用的C编译的可执行程序,关闭脚本内容如下:

#!/bin/bash
PID=$(pgrep xxx)
if [ "$PID" != "" ]; then
    kill $PID
fi

这两年程序开发语言换成了go。但是编译可执行程序后的关闭脚本仍然沿用了上面的脚本

然后问题来了,小伙伴做了一个可执行的程序命名规则是psbc-monitor-reporter:

问题来了,屡试不爽的脚本,竟然没有杀死该进程?尝试了一下老的程序跟脚本:

这是没有问题的啊?对比一下两个进程,区别也就在中划线下划线?分割两个or三个

尝试修改进程名字中划线为下划线:

先关闭运行中的进程:

ps -aux|grep psbc-monitor-reporter
kill 3070234

修改进程名称,并启动服务

ps -aux|grep psbc-monitor-reporter
kill 3070234
bash mv psbc-monitor-reporter psbc_monitor_reporter

修改启动脚本:

[root@k8s-master-01 psbc-monitor-reporter]# cat start.sh 
#!/bin/bash
# 启动 myserver
./psbc_monitor_reporter &
echo "服务已启动!"

启动脚本:

sh start.sh

执行关闭脚本:

仍然无效?继续尝试一下修改为分割线两位?

继续尝试一下修改为分割线两位:

同上,先关闭进程:

修改可执行程序名称:

mv psbc_monitor_reporter monitor-reporter

修改启动脚本,启动服务:

继续执行关闭脚本:

依然杀不死?

确认过滤不到进程?继续回归下划线看看?

回归下划线看看:

继续关闭进程:

修改可执行程序名称,修改启动脚本,启动服务:

关闭服务尝试:

严重怀疑人生:

继续调整进程名称及关闭脚本,但仍未成功。即使是最极简的名称形式monitor_reporter,使用pgrep依然无法找到对应进程,而ps aux|grep monitor_reporter却能显示。

杀掉进程:

kill 164143

深入分析

问题原因

pgrep默认只搜索进程名称,而不是整个命令行。如果进程的命令行名称与实际运行时的命令名称不完全相同,pgrep可能无法正确找到进程。

解决方案

恢复可执行程序名称:

mv monitor_reporter psbc-monitor-reporter

使用pgrep的-f选项,它可以匹配整个命令行。调整脚本如下:

#!/bin/bash 
PID=$(pgrep -f psbc-monitor-reporter) 
if [ "$PID" != "" ]; then 
    kill $PID 
fi 

-f选项让pgrep搜索包括整个命令行在内的文字,这种方式更加灵活且适用于命令行参数中含有多种可变元素的情况。

结论

通过深入了解pgrep的使用限制及其选项,我们成功解决了Go语言编译的程序在Linux环境下无法被传统关闭脚本杀死的问题。这一发现不仅提升了我们的系统管理效率,也增加了对Linux进程管理工具更深层次的了解。在实际运用中,建议尽量使用pgrep -f以保证脚本的可靠性和鲁棒性。

这个案例进一步体现了在系统管理和脚本编写中,细节的重要性和对工具深入理解的必要性。希望这篇文章能帮助到面临类似问题的你!