killall gives me `no process found ` but ps
Is this on Linux?
There are actually a few subtly different versions of the command name that are used by ps
, killall
, etc.
The two main variants are: 1) the long command name, which is what you get when you run ps u
; and 2) the short command name, which is what you get when you run ps
without any flags.
Probably the biggest difference happens if your program is a shell script or anything that requires an interpreter, e.g. Python, Java, etc.
Here's a really trivial script that demonstrates the difference. I called it mycat
:
#!/bin/sh
cat
After running it, here's the two different types of ps
.
Firstly, without u
:
$ ps -p 5290
PID TTY ... CMD
5290 pts/6 ... mycat
Secondly, with u
:
$ ps u 5290
USER PID ... COMMAND
mikel 5290 ... /bin/sh /home/mikel/bin/mycat
Note how the second version starts with /bin/sh
?
Now, as far as I can tell, killall
actually reads /proc/<pid>/stat
, and grabs the second word in between the parens as the command name, so that's really what you need to be specifying when you run killall
. Logically, that should be the same as what ps
without the u
flag says, but it would be a good idea to check.
Things to check:
- what does
cat /proc/<pid>/stat
say the command name is? - what does
ps -e | grep db2
say the command name is? - do
ps -e | grep db2
andps au | grep db2
show the same command name?
Notes
If you're using other ps flags too, then you might find it simpler to use ps -o comm
to see the short name and ps -o cmd
to see the long name.
You also might find pkill
a better alternative. In particular, pkill -f
tries to match using the full command name, i.e. the command name as printed by ps u
or ps -o cmd
.
killall tries to match on a process name (but is not really that good at the matching part).
And since "ps | grep" and "ps | grep | kill" does a much better job, someone simplified this and created pgrep and pkill. Read that commands like "ps grep" and "ps kill", since that command first ps then grep and if wanted kills.
I had a similar problem but /proc/<pid>/stat
contained the expected string. By using strace I could see that killall also accessed /proc/<pid>/cmdline
.
I continued to investigate using gdb to find that in my case it failed on a check of my command to the full command including all args found in /proc/<pid>/cmdline
. It seemed like that path of the code triggered due to the filename being longer than 15 chars (which is a hardcoded value in the source of killall). I didn't fully investigate if I could somehow getting it to work with killall.
But as mentioned in other comments here pkill is a better alternative that does not have the same issues.
The source code of pkill
can be found here https://github.com/acg/psmisc for the interested.