How to get pid of process with exact name?
I am trying to get id of process name systemctl stop Myservice but not exact pid through this command
if(0 == system("pidof -x systemctl stop Myservice > /dev/null")) {
//A process is running.
}
This code is giving pid of systemctl start Myservice also if it is running in system, need to get specific pid for this process name "systemctl stop Myservice" only?
If available on your system pgrep
seems like a good fit here
pgrep -xf "systemctl stop Myservice"
pgrep
is provided by the same package as ps
(at least it is on the CentOS 7 system I referred to)
$ 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
Even lightweight distros using BusyBox seem to be OK from a narrow test:
$ 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]
[...]
So I would think that if you have ps
you can rely on pgrep
, though things could be a bit less certain if your code ends up running inside a container (though this scenario seems pretty unlikely, given what you’re attempting to do).
Are you trying to catch the systemctl stop ...
command in action? This seems like it would be quite prone to race conditions and/or performance issues. What if the C program loops too slowly and misses the command running, or too quickly and consumes excessive CPU?
If your goal is simply to detect when the service leaves active
state, this approach might be better:
systemctl status Myservice | grep -qE "^ +Active: active"
This should return a non zero exit code if the service is in anything other than active state.
As per your use case, it might be necessary to only flag when the state changes — rather than every time it sees non-active, via some additional logic.
On Linux, the process name is a sequence of 0 to 15 bytes used to name processes. The name of a process changes any time that command executes a command to the first 15 bytes of the basename of the file being executed or when using pctrl(PR_SET_NAME)
for instance.
That systemctl stop Myservice
looks more like the concatenation with spaces of 3 arguments passed to /usr/bin/systemctl
when it was executed by the process or one of its ancestors.
Assuming you want the pids of processes that are currently executing a /usr/bin/systemctl
that was passed the systemctl
, stop
and Myservice
arguments upon execution, on Linux, the approach would be to:
- do a
stat()
on/proc/*/exe
files and check that thest_dev
andst_ino
are the same as that returned bystat("/usr/bin/systemctl")
(assuming thatsystemd
has not been updated since the process executedsystemctl
). - and then check that the
/proc/<pid>/cmdline
file for the corresponding process containssystemctl<NUL>stop<NUL>Myservice<NUL>
(bearing in mind that processes can — though generally don’t — modify that arbitrarily).
I can’t think why you’d want to do that though, especially in a C / C++ program. That looks like an XY Problem.