Centos 6 和 Centos 8 之间的 ps -C 行为发生了变化

Centos 6 和 Centos 8 之间的 ps -C 行为发生了变化

我们的系统经常用来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,最好不要重写大量代码。

  1. 有没有办法ps在版本之间获得相同的行为? (由于名称冲突,可能无法将命令名称截断为前 15 个字符)

  2. 是否有另一种方法来检测该过程? (有很多代码,并且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 swapprocps-ng它开始。这不是最安全的方法,这将用旧版本替换相当多的系统程序。

因此,您可能想procps以完全不同的名称重建并仅安装它ps,例如/opt/el6-rebuilds/bin/ps。然后,您可以PATH通过工具确保包含目录位于系统上/etc/profile.d。结果将是psCentOS 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 相匹配。

相关内容