我们的系统经常用来ps -C cmdName
检查进程是否正在运行,如果没有,则重新启动它。
从 Centos 6 迁移到 Centos 8 时,行为似乎ps -C
发生了变化,这破坏了我们系统的大部分内容。
Centos 6(32 位)
是的,流程在那里:
# ps aux | grep DvBuildSegmentList
root 16223 4.0 0.1 16064 11272 pts/0 S 14:14 0:00 ./DvBuildSegmentList
root 16264 0.0 0.0 4416 1880 pts/0 S+ 14:14 0:00 grep DvBuildSegmentList
并ps -C
在完整命令名称上检测进程:
# ps -C DvBuildSegmentList
PID TTY TIME CMD
16223 pts/0 00:00:00 DvBuildSegmentL
(注意输出中截断的命令行)
Centos 8(64 位)
是的,流程在那里:
# ps aux | grep DvBuildSeg
root 15282 0.9 0.2 99796 42424 pts/1 S 14:18 0:04 ./DvBuildSegmentList
root 16989 0.0 0.0 221900 1104 pts/1 S+ 14:26 0:00 grep --color=auto DvBuildSeg
使用完整命令名没有输出:
# /bin/ps -C DvBuildSegmentList
PID TTY TIME CMD
但使用缩短的命令名称确实可以检测到该进程:
# /bin/ps -C DvBuildSegmentL
PID TTY TIME CMD
15282 pts/1 00:00:06 DvBuildSegmentL
我们需要同时维护 32 位 Centos 6 和 64 位 Centos 8,最好不要重写大量代码。
有没有办法
ps
在版本之间获得相同的行为? (由于名称冲突,可能无法将命令名称截断为前 15 个字符)是否有另一种方法来检测该过程? (有很多代码,并且
ps -C
方法遍布 C++、perl、php 和 bash)
编辑我
就其价值而言, 的内容/proc/<pid>/stat
显示了截断的文件名:
cat /proc/4605/stat
4605 (DvBuildSegmentL) S 25769 4605 25769 34817 4605 1077936384 10536 304 0 0 225 119 0 0 20 0 1 0 6717759 103620608 10945 18446744073709551615 4194304 4339868 140734307933616 0 0 0 0 4096 16901 1 0 0 17 4 0 0 0 0 0 6438088 6440229 11730944 140734307937640 140734307937666 140734307937666 140734307938275 0
但是,/proc/<pid>/cmdline
确实有完整的命令名称,尽管前面带有完整路径
cat -v /proc/4605/cmdline
/usr/local/blah/blah/blah/DvBuildSegmentList^@-d^@2^@
答案1
我设想解决此差异的一种方法是重建 CentOS 6 版本的procps
软件包,然后yum swap
从procps-ng
它开始。这不是最安全的方法,这将用旧版本替换相当多的系统程序。
因此,您可能想procps
以完全不同的名称重建并仅安装它ps
,例如/opt/el6-rebuilds/bin/ps
。然后,您可以PATH
通过工具确保包含目录位于系统上/etc/profile.d
。结果将是ps
CentOS 8 中使用的“相当于 CentOS 6”版本。
但话虽如此,您确定有这种区别吗?刚刚在我的 RHEL 8 上尝试过ps -C <program name>
,并且在准确指定时工作得很好(实际上你说的是相反,它仅在通过部分字符串指定时才工作)。
答案2
这两种方法似乎适用于不同的操作系统版本:
grep 获取进程名称
ps aux | grep myLongProcessName | grep -v
如果进程正在运行,则返回 0;如果未找到进程,则返回 1。需要第二个grep -v
是因为有时(但并非总是)grep
命令本身出现在 的输出中grep myLongProcessName
。
通过killall发送信号0
killall -0 myLongProcessName
0
如果进程存在则返回,1
如果未找到则返回。
如果实际上是另一个进程的子字符串,则“double grep
”方法会失败。myLongProcessName
例如。如果我们有三个进程:
longProcessDBAccess
(未运行)longProcessDBAccessManager
(跑步)longProcessDBAccessClient
(跑步)
使用“double grep
”方法检查是否longProcessDBAccess
正在运行将会失败,因为它还会检测到其他两个方法是否存在。
但是,为了使该killall
方法发挥作用,uid
正在运行的处理killall
必须具有这样做的权限。
杀:
该
kill()
函数应向 指定的一个进程或一组进程发送信号pid
。要发送的信号由 指定,sig
并且是 中给出的列表中的 1<signal.h>
或 0。如果sig
是 0(空信号),则执行错误检查,但实际上不发送任何信号。空信号可用于检查 的有效性pid
。对于有权向 指定的进程发送信号的进程
pid
,除非发送进程具有适当的权限,否则发送进程的真实或有效用户 ID 应与接收进程的真实或保存的 set-user-ID 相匹配。