Can’t kill a process that’s running—yet apparently not visible—in the task manager
Solution 1
Did you notice that you got two different PIDs in the two tries?
Consider this: if you type a command like vi raven.txt
,
then ps ax
will display a line that shows a command of vi raven.txt
.
Likewise, if you type a command like grep snappr
,
then ps ax
will display a line that shows a command of grep snappr
.
And, if you pipe the output of that ps
through grep snappr
,
the grep
will find the line that is describing itself.
So, if you type
$ ps ax | grep snappr | awk '{print $1}'
repeatedly, it will print a different number every time
(because it's printing the PID of grep
,
and you get a new, unique grep
process every time you run the command).
Finally, consider: the kill
command cannot be executed until its argument(s) are known.
For its argument to be known, the $(ps ax | grep snappr | awk '{print $1}')
pipeline
must have completed. This implies that the grep
must have terminated1.
Therefore, the kill
is being given the PID of the grep
process,
but only after the grep
process has terminated --
so, naturally, it reports "No such process".
Perhaps I should have mentioned that there is no snappr
process running.
If there were, your first command would output two numbers: the PID of snappr
,
and the PID of grep snappr
.
Now, if snappr
were running, your command might start running semi-correctly,
by which I mean it does what you want but also gives an error message.
If the snappr
is running with PID 42097, and grep snappr
runs with PID 70848,
then the kill
command will be kill 42097 70858
, which will kill the snappr
and get an error message from trying to kill the grep
process that no longer exists.
You'll probably want to improve on this. My favorite way, which I invented 20 years ago,
it to change the grep
to grep "[s]nappr"
, which will match snappr
but will not match itself.
Another approach is to use pgrep
rather than ps | grep
.
1 Alternatively, the awk
could finish if the grep
merely closed its stdout.
This would be very unusual behavior for a *nix program.
Solution 2
Shorter Answer
Don’t jump through Bash hoops to kill snappr
with ps
, piped through grep
and then piped through awk
like that. Instead try to kill it like this using pkill
; no muss or fuss and it targets based on process name out of the box:
sudo pkill snappr
Longer Answer
Not too clear with how Snapper operates on a system process level, but the issue could be that you are only grabbing the child process ID instead of the parent process ID.
In fact I believe the method you are using to grab a process ID (ps ax | grep snappr | awk '{print $1}'
) would return a whole list of process IDs connected to snappr
regardless of whether it is parent or child. So using that you might kill one process ID that is just a child process ID yet the parent ID would still be active and able to “spawn” another child process to compensate.
So perhaps you can do something like this to grab the definitive parent ID of whatever process ID you feed it and act on it; simple proof of concept of how it works:
ps -p [process ID] -o ppid=
Running that bare command in Bash will give you the parent process ID of the child process ID you put in [process ID]
. So if the child ID 4567
has a parent process ID of 123
then the command would be:
ps -p 4567 -o ppid=
And that would return, 123
.
That said, this could be a dangerous way of dealing with a stray process since if your script grabs the actual parent process ID of snapper
, then the parent of that process ID could really be your own Bash shell. So you might inadvertently just kill your Bash shell instead of the snapper
knocking you off the system while leaving snapper
process running.
But all that said, why not make your life easier and just run pkill
like this:
sudo pkill snappr
That will kill all processes connected to snappr
without any fancy command line juggling.
Related videos on Youtube
aweeeezy
Updated on September 18, 2022Comments
-
aweeeezy over 1 year
I started an application that won’t run, yet I can’t delete it cause it’s still running. I can print the PID, but not kill the process using it.
~ $ ps ax | grep snappr | awk '{print $1}' 70824 ~ $ kill $(ps ax | grep snappr | awk '{print $1}') -bash: kill: (70832) - No such process
-
gogoud about 9 yearsI have a bash script which I only want running once on my machine. Within the script I use this code to check (where $THIS is the name of the script):
PRIOR="$(ps --no-headers -Ao "pid,ppid,sid,args"|grep "$THIS"|grep -Ev "(grep |$PPID |$$ |<defunct>)")"
. If $PRIOR is not null then the script is already running. I've had more success with this than withpgrep
. -
Scott - Слава Україні about 9 yearsOf course, if you're trying to kill a process that you started (as stated in the question), as long as it isn't setuid, you own the process, and you don't need
sudo
. And you should not usesudo
if you don't need to. -
Scott - Слава Україні about 9 yearsAh, yes, the old
grep | grep -v
solution. Why run an extra process that you don't need? Work smarter, not harder. -
gogoud about 9 yearsI agree it looks messy. I'd be happy to find a better, reliable, way. ps -C doesn't catch all processes, pgrep includes defunct processes.
-
Scott - Слава Україні about 9 years(1) Do you know of any problem with my
grep "[s]nappr"
solution? (2) As long as we're talking about killing processes, who cares whether defunct processes are included? Killing a defunct process is a no-op. -
gogoud about 9 yearsI realise we are getting off-topic here. I like your [s]napper solution! But I need to exclude defuncts because I really want to know if there is a live process out there (in which case, stop now!) or just something that is dying. And I not only need to exclude the grep call I also need to exclude the running instance of the script itself ($$), and possibly the parent that called it ($PPID).
-
Sobrique about 9 yearsMore likely - the process doesn't actually exist,
grep
is matching itself. -
Olivier Dulac about 9 years+1 for a good answer (but... invented the [x] trick 20 years ago? or just read about it in the Unix FAQ ? ;) )
-
dan about 9 yearsI prefer this trick
ps ax | egrep "[ /](PID|${command})"
orps ax | grep "[ /]${command}"
to avoid the 3 times stupidgrep ${command} | grep -v grep
. -
Hongxu Chen about 9 yearsuse
killall
instead ofpkill
since by defaultpkill
overkills.