如何获取具有确切名称的进程的pid?

如何获取具有确切名称的进程的pid?

我试图通过此命令获取进程名称 systemctl stop Myservice 的 id,但不是确切的 pid

   if(0 == system("pidof -x systemctl stop Myservice  > /dev/null")) {
  //A process is running.
   }

此代码给出了 systemctl start Myservice 的 pid,如果它在系统中运行,则仅需要获取此进程名称“systemctl stop Myservice”的特定 pid?

答案1

如果在您的系统上可用pgrep似乎很适合这里

pgrep -xf "systemctl stop Myservice"

pgrep由相同的软件包提供ps(至少在我提到的 CentOS 7 系统上)

$ rpm -q --whatprovides $(which pgrep)
procps-ng-3.3.10-28.el7.x86_64
$ rpm -q --whatprovides $(which ps)
procps-ng-3.3.10-28.el7.x86_64

即使是使用 BusyBox 的轻量级发行版似乎通过狭窄的测试就可以了:

$ docker run --rm alpine pgrep --help
BusyBox v1.35.0 (2022-05-09 17:27:12 UTC) multi-call binary.

Usage: pgrep [-flanovx] [-s SID|-P PPID|PATTERN]
[...]

所以我认为,如果你有,ps你可以依赖pgrep,尽管如果你的代码最终在容器内运行,事情可能会不太确定(尽管考虑到你正在尝试做的事情,这种情况似乎不太可能发生)。

您是否想捕捉systemctl stop ...正在执行的命令?这似乎很容易出现竞争条件和/或性能问题。如果 C 程序循环太慢而错过了正在运行的命令,或者太快并消耗过多的 CPU,该怎么办?

如果您的目标只是检测服务何时离开active状态,那么这种方法可能会更好:

systemctl status Myservice | grep -qE "^ +Active: active"

如果服务处于活动状态以外的任何状态,这应该返回非零退出代码。

根据您的用例,可能需要仅在状态更改时进行标记 - 而不是每次看到非活动状态时,通过一些附加逻辑进行标记。

答案2

在 Linux 上,进程名称是用于命名进程的 0 到 15 个字节的序列。每当该命令将命令执行到正在执行的文件的基本名称的前 15 个字节或使用时,进程的名称都会更改pctrl(PR_SET_NAME)

这看起来更像是由进程或其祖先之一执行时systemctl stop Myservice传递给 3 个参数的空格的串联。/usr/bin/systemctl

假设您想要当前正在执行的进程的 pid,/usr/bin/systemctl该进程在执行时传递了systemctl,stopMyservice参数,在 Linux 上,方法是:

  • stat()对文件执行 a/proc/*/exe并检查st_devst_ino是否与返回的相同stat("/usr/bin/systemctl")(假设systemd自进程执行以来尚未更新systemctl)。
  • 然后检查/proc/<pid>/cmdline相应进程的文件是否包含systemctl<NUL>stop<NUL>Myservice<NUL>(请记住,进程可以(尽管通常不会)任意修改该文件)。

我不明白你为什么要这样做,尤其是在 C / C++ 程序中。这看起来像一个XY问题

相关内容