Can’t kill a process that’s running—yet apparently not visible—in the task manager

12,954

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.

Share:
12,954

Related videos on Youtube

aweeeezy
Author by

aweeeezy

Updated on September 18, 2022

Comments

  • aweeeezy
    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
    gogoud about 9 years
    I 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 with pgrep.
  • Scott - Слава Україні
    Scott - Слава Україні about 9 years
    Of 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 use sudo if you don't need to.
  • Scott - Слава Україні
    Scott - Слава Україні about 9 years
    Ah, yes, the old grep | grep -v solution. Why run an extra process that you don't need? Work smarter, not harder.
  • gogoud
    gogoud about 9 years
    I 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 - Слава Україні
    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
    gogoud about 9 years
    I 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
    Sobrique about 9 years
    More likely - the process doesn't actually exist, grep is matching itself.
  • Olivier Dulac
    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
    dan about 9 years
    I prefer this trick ps ax | egrep "[ /](PID|${command})" or ps ax | grep "[ /]${command}" to avoid the 3 times stupid grep ${command} | grep -v grep.
  • Hongxu Chen
    Hongxu Chen about 9 years
    use killall instead of pkill since by default pkill overkills.