我试图通过此命令获取进程名称 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
,stop
和Myservice
参数,在 Linux 上,方法是:
stat()
对文件执行 a/proc/*/exe
并检查st_dev
和st_ino
是否与返回的相同stat("/usr/bin/systemctl")
(假设systemd
自进程执行以来尚未更新systemctl
)。- 然后检查
/proc/<pid>/cmdline
相应进程的文件是否包含systemctl<NUL>stop<NUL>Myservice<NUL>
(请记住,进程可以(尽管通常不会)任意修改该文件)。
我不明白你为什么要这样做,尤其是在 C / C++ 程序中。这看起来像一个XY问题。