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以保证脚本的可靠性和鲁棒性。
这个案例进一步体现了在系统管理和脚本编写中,细节的重要性和对工具深入理解的必要性。希望这篇文章能帮助到面临类似问题的你!