Just a note: pidof
MAY treat everything after the last slash as the program name
:
fang@debian:~$ ps -ax | grep k3s | head -n1
528 ? Ssl 634:37 /usr/local/bin/k3s server
fang@debian:~$ pgrep k3s
528
fang@debian:~$ pidof k3s
fang@debian:~$ pidof /usr/local/bin/k3s
fang@debian:~$ pidof '/usr/local/bin/k3s server'
528
fang@debian:~$ pidof 'k3s server'
528
Update: As Stéphane Chazelas said, pidof
actually match any of:
Name:
field in /proc/pid/status
- the first argument in
/proc/pid/cmdline
- the base name of the first argument in
/proc/pid/cmdline
In most cases, there should be a NUL
after each arg. eg. sleep:
fang@debian:~$ sleep infinity &
[1] 2076966
fang@debian:~$ pidof sleep
2076966
fang@debian:~$ xxd /proc/2076966/cmdline
00000000: 736c 6565 7000 696e 6669 6e69 7479 00 sleep.infinity.
fang@debian:~$ head -n1 /proc/2076966/status
Name: sleep
It is a bit special because the argv[0]
contains a whitespace:
fang@debian:~$ ls -l /usr/local/bin/k3s
-rwxr-xr-x 1 root root 54001664 7月 3 20:16 /usr/local/bin/k3s
fang@debian:~$ head -n1 /proc/528/status
Name: k3s-server
fang@debian:~$ head -n1 /proc/528/cmdline && echo
/usr/local/bin/k3s server
fang@debian:~$ xxd /proc/528/cmdline
00000000: 2f75 7372 2f6c 6f63 616c 2f62 696e 2f6b /usr/local/bin/k
00000010: 3373 2073 6572 7665 7200 0000 0000 0000 3s server.......
In conclusion, to get its pid, you can:
fang@debian:~$ pgrep k3s-server
528
fang@debian:~$ pidof k3s-server
528
fang@debian:~$ pidof 'k3s server'
528
You cannot:
fang@debian:~$ pgrep 'k3s server'
Because it only match
Name:
field in /proc/pid/status
- (Seems it is the same to the part inside
(...)
in /proc/pid/stat
, right?)
pgrep
matches on the process name (theName:
field in/proc/pid/status
or the part inside(...)
in/proc/pid/stat
as show withps -o comm
) by default whilepidof
matches on theargv[0]
(or its basename as you rightly point out) of the last execve() the process or its ancestor made (/proc/pid/cmdline
,ps -o args
), falling back to the process name only if argv[0] is empty or there's no args (execve() called with an empty arg list, or kernel tasks that have never run a execve()).pgrep -f
matches on the arg list (joined with spaces) – Stéphane Chazelas Aug 01 '23 at 05:51pidof
is fromsysvinit-utils
version 3.07),pidof
only matches on the process name ifargv[0]
is empty or unset. Afterexec -a foo sleep 20 &
,pidof foo
matches but notpidof sleep
. While withexec -a '' sleep 20
,pidof sleep
matches butpidof ''
doesn't. – Stéphane Chazelas Aug 01 '23 at 13:01Name:
in/proc/pid/status
is the same as part inside(...)
in /proc/pid/stat which is the process name (note: it's limited to 15 bytes on Linux), except that in/proc/pid/status
some characters are encoded using backslash escape sequences. For instance newline is represented as\n
. For the text thatpgrep
regexps match against, it seems those characters are replaced with?
. Forpidof
I don't know. – Stéphane Chazelas Aug 01 '23 at 13:11