121

When I try to exit from my Linux server I get the message:

There are stopped jobs.

: Is there a single command to kill these?

yazz.com
  • 6,743
  • 14
  • 37
  • 38
  • Additional examples in thie U&L Q&A: http://unix.stackexchange.com/questions/124428/terminate-every-background-process – slm Apr 12 '14 at 20:25
  • I had opposite problem now, it would not warn about stopped jobs when I quit the shell! Had to put `shopt -s checkjobs` in my .bashrc – Sam Watkins Jul 09 '14 at 05:59
  • 2
    press ctrl + d again, it will let you exit now, killing those jobs in the process – Jens Timmerman May 18 '16 at 12:05

8 Answers8

113

To quickly kill all the stopped jobs under the bash, enter:

kill -9 `jobs -ps`

jobs -ps lists the process IDs (-p) of the stopped (-s) jobs.
kill -9 `jobs -ps` sends SIGKILL signals to all of them.

Isti115
  • 103
  • 4
ooshro
  • 10,874
  • 1
  • 31
  • 31
  • 23
    -1 for "kill Jobs" –  Aug 10 '12 at 21:44
  • 1
    didn't work when the job was "sudo su". i.e. `sudo kill \`jobs -p\`` didnt work but explicitly typing PID did. – user13107 Oct 27 '12 at 18:12
  • 15
    Why is this upvoted so highly? It's wrong. If the processes are stopped, then a `kill` such as this will do nothing, since the processes are stopped, they won't process the SIGTERM (-15) that is sent to them by default. – slm Apr 12 '14 at 20:18
  • 10
    kill -9 will do the trick. – timetofly Oct 12 '14 at 17:36
91

Try typing this:

kill -9 $(jobs -p)
dukevin
  • 1,610
  • 3
  • 18
  • 25
  • 11
    That should do it, but I think he should send first a SIGTERM (-15) before sending a SIGKILL (-9). So perhaps proposing something like "kill $(jobs -p) ; sleep 3s ; kill -9 $(jobs -p)" would be better. Sending SIGTERM first the jobs may be able to do a clean exit (freeing allocated resources, etc). – rems Feb 25 '11 at 10:49
  • 3
    Kevin Duke, your answer is the one that worked for me. I couldn't vote because I don't have 15 in reputation. kill -9 $(jobs -p) –  Aug 10 '12 at 21:33
  • 2
    @rems Except, as slm pointed out, they won't get the SIGTERM because they're stopped. – Paul Gear Jul 22 '14 at 23:59
  • 2
    Does not work on zsh. Due to [zsh not being POS](http://www.zsh.org/mla/workers/2006/msg00067.html) [IX compliant with jobs](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=346162). – Max Coplan Oct 27 '18 at 00:38
  • Then, how to deal with zsh? – fx-kirin Mar 01 '19 at 05:49
17

The accepted answer would kill all jobs (which is sufficient in this case) and not merely the stopped ones. Should you want to kill only the Stopped ones, run:

kill $(jobs -l | grep Stopped | cut -d' ' -f3)
Kit Sunde
  • 946
  • 3
  • 12
  • 31
14

The easiest way is actually to simply immediately retry the exit; bash will take that to mean "kill all stopped jobs and exit".

geekosaur
  • 7,025
  • 1
  • 19
  • 19
7
for x in `jobs -p` ; do kill -9 $x ; done
Jenny D
  • 27,358
  • 21
  • 74
  • 110
monu
  • 171
  • 1
  • 4
  • 2
    you can add code formatting for this line to make it easier to read. – drcelus Feb 26 '13 at 10:54
  • Can you take a look at your formatting again - use four spaces at the start of the line to mark a block as code (rather than using backtick). Right now it isn't clear whether you are using backticks in your code, or trying to display code using backticks. – dunxd Feb 26 '13 at 11:39
  • 1
    The formatting is fine. we have to pass the jobs -p using backticks else it wont consider as a command, and it will throw an error. – monu Feb 27 '13 at 06:01
6

Normally if you got that message, you need to logout twice. E.g. first Ctrl+D gives you the warning message to inform you about stopped jobs, pressing for the second time will log you out killing the jobs. This the same applies to logout and exit commands.

To kill them manually, try: kill $(jobs -p).


If you don't want to kill jobs from your current shell, you can remove them from the table of active jobs without killing by using disown command. E.g.

$ sleep 1000 &
[1] 19404
$ jobs
[1]+  Running                 sleep 1000 &
$ disown

Stopped jobs also can be determined by the state of the process (T character) which means the process was stopped by signal such as SIGSTOP, SIGTSTP or other (like SIGTTIN, or SIGTTOU).

In case when jobs a shell builtin command is not available, stopped processes can be listed by the following command:

ps wuax | awk '$8 ~ "T"'

To kill them all, you can basically type:

kill -9 $(ps wuax | awk 'NR>1 && $8 ~ "T" {print $2}')

Here is a simple test:

$ sleep 1000 &
[1] 2014
$ sleep 1000 &
[2] 2015
$ sleep 1000 &
[3] 2016
$ sleep 1000 &
[4] 2017
$ killall -STOP sleep
[1]   Stopped                 sleep 1000
[2]   Stopped                 sleep 1000
[3]   Stopped                 sleep 1000
[4]   Stopped                 sleep 1000
$ ps wuax | awk '$8 ~ "T"'
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
vagrant   2014  0.0  0.0   7228   832 pts/0    T    20:38   0:00 sleep 1000
vagrant   2015  0.0  0.0   7228   708 pts/0    T    20:38   0:00 sleep 1000
vagrant   2016  0.0  0.0   7228   760 pts/0    T    20:38   0:00 sleep 1000
vagrant   2017  0.0  0.0   7228   828 pts/0    T    20:38   0:00 sleep 1000
$ kill -9 $(awk 'NR>1 && $8 ~ "T" {print $2}' <(ps wuax))
$ jobs
[1]   Killed                  sleep 1000
[2]   Killed                  sleep 1000
[3]   Killed                  sleep 1000
[4]   Killed                  sleep 1000
kenorb
  • 5,943
  • 1
  • 44
  • 53
6

Just in case this helps someone else -- most people are here because they have some stopped processes that they started, backgrounded via the shell maybe. I needed to find processes, as root, stopped by other users, for which variants on the jobs command won't do.

A bit of digging around with man ps got me to this:

ps -a -o pid,user,cmd,state | grep 'T$'

Explanation: the -a flag says show all processes, then -o controls output, what info will be shown about each process. I'm choosing pid, user, cmd (the command line), and state, which is the process state.

From man ps:

PROCESS STATE CODES
   Here are the different values that the s, stat and state output specifiers (header "STAT" or "S") will display to describe the
   state of a process:
           D    uninterruptible sleep (usually IO)
           R    running or runnable (on run queue)
           S    interruptible sleep (waiting for an event to complete)
           T    stopped, either by a job control signal or because it is being traced
           W    paging (not valid since the 2.6.xx kernel)
           X    dead (should never be seen)
           Z    defunct ("zombie") process, terminated but not reaped by its parent

so finally I pipe it to grep T$ which says, show me all the processes that have T in the last column.

And then I have a nice list of all the processes from different users that are in the stopped state.

$ ps -a -o pid,user,cmd,state | grep 'T$'
  865 joson74+ python                      T
  885 joson74+ sh -c less                  T
  886 joson74+ less                        T
 1014 minames+ python3.4 -i /home/minames  T
 5352 MooKo    nano stdio.h                T
 7851 harry    tmux attach                 T
12083 harry    tmux attach                 T
13495 gorylla+ python3.4 -i /home/gorylla1 T
18009 conr1d   vim                         T
19664 enythin+ python                      T
24906 wardlist python                      T
hwjp
  • 398
  • 5
  • 7
  • To get stopped jobs attached to current shell, `jobs -ps` is simpler than this answer. That being said, this answer doesn't show only jobs stopped via `Ctrl-Z` in a shell, but **all stopped jobs: other shells, other users**, including jobs being debugged (e.g. by gdb). – Stéphane Gourichon May 25 '18 at 07:50
  • For me the best answer, but not exactly working. I had to use `ps -el | grep T` to find the processes in state 'T'. – dr0i Feb 01 '19 at 08:28
5

If you want to remove some stopped jobs but not all, try this:

First, list jobs, you will get something like this:

$ jobs -l

[2]   4813 Stopped                 ./parse < call.txt
[3]-  4819 Stopped                 ./parse < call.txt

send kill to a stopped job, it will do nothing but queue than bring it in in foreground, it will terminate

$ fg %2
./parse < call.txt
Terminated

$ jobs -l
[3]-  4819 Stopped                 ./parse < call.txt
Michael Hampton
  • 237,123
  • 42
  • 477
  • 940
sergei
  • 51
  • 1
  • 1