As in the title - how to kill all background processes in zsh?
5 Answers
alias killbg='kill ${${(v)jobstates##*:*:}%=*}'
. It is zsh, no need in external tools.
If you want to kill job number N:
function killjob()
{
emulate -L zsh
for jobnum in $@ ; do
kill ${${jobstates[$jobnum]##*:*:}%=*}
done
}
killjob N
-
1@ZachRiggle It is in `man zshexpn` and `man zshmodules`: `$jobstates` is a associative array parameter, `(v)` selects only values from this array, `#` makes zsh remove given pattern starting from the start of string, selects least lengthy pattern for removal, `*:*:`: pattern that makes zsh remove first two colon-separated fields of each value (`#` on array parameters is applied to each value), `%` is like `#`, but for end of strings and `=*` makes zsh remove everything after the last eq sign including the sign itself. Each `$jobstates` value looks like `job-state:mark:pid=state...`. – ZyX Sep 05 '14 at 14:58
-
It appears I have a bug here: it does not work if the whole pipe was suspended. – ZyX Sep 05 '14 at 15:00
-
1**Update**: changed `#` to `##`: this way it will remove everything up to the last colon, effectively leaving only last process in the pipe. I am working under an assumption that last one will always be alive, otherwise more complex computations should be performed. – ZyX Sep 05 '14 at 15:07
one should use the builtin
zsh built-in command alongside with the other kill
zsh built-in command as:
builtin kill %1
as kill
is also a separate binary file from util-linux
package (upstream, mirror) located in /usr/bin/kill
which does not support jobs (kill: cannot find process "%1"
).
use keyword builtin
to avoid name conflict or enable
the kill
built-in if it is disabled.
there is a concept of disabling and enabling built-in commands (ie. shell's own commands such as cd
and kill
) in shells, and in zsh you can enable (a disabled) kill
builtin as:
enable kill
issue disable
to check if the builtin is disabled (and enable
to see the enabled ones).
-
The question was how to kill **_all_** background processes. If you have 100s, doing it one-by-one ain't gonna cut it, however useful it is to know about this `builtin` vs. file conflict namespace conflict. – ijoseph Dec 16 '22 at 18:02
Minor adjustment to @Zxy's response...
On my system, I found that suspended jobs weren't killed properly with the default kill signal. I had to actually change it to kill -KILL
to get suspended
background jobs to die properly.
alias killbg='kill -KILL ${${(v)jobstates##*:*:}%=*}'
Pay special attention to the SINGLE QUOTES around this. If you switched to double quotes, you would need to escape the each "$". Note that you can NOT use a function
to wrap this command since the function will increment the $jobstates
array causing the function to try killing itself... Must use an alias.
The killjob
script above is a bit redundant since you can just do:
kill %1
Less keystrokes and it's already build into zsh
.

- 442
- 6
- 13
This works for both ZSH and Bash:
: '
killjobs - Run kill on all jobs in a Bash or ZSH shell, allowing one to optionally pass in kill parameters
Usage: killjobs [zsh-kill-options | bash-kill-options]
With no options, it sends `SIGTERM` to all jobs.
'
killjobs () {
local kill_list="$(jobs)"
if [ -n "$kill_list" ]; then
# this runs the shell builtin kill, not unix kill, otherwise jobspecs cannot be killed
# the `$@` list must not be quoted to allow one to pass any number parameters into the kill
# the kill list must not be quoted to allow the shell builtin kill to recognise them as jobspec parameters
kill $@ $(sed --regexp-extended --quiet 's/\[([[:digit:]]+)\].*/%\1/gp' <<< "$kill_list" | tr '\n' ' ')
else
return 0
fi
}
@zyx answer didn't work for me.
More on it here: https://gist.github.com/CMCDragonkai/6084a504b6a7fee270670fc8f5887eb4

- 6,222
- 12
- 56
- 98
alias killbg='for job in \`jobs -l | egrep -o "([0-9][0-9]+)"`;

- 10,999
- 13
- 68
- 158
-
Super! Now try suspending `echo 123 | less` and check out what it will kill. Hint: by the time you run `kill` `echo 123` process will already be dead and its PID may already have been taken. So with such suspended pipe with your `killbg` you may kill 2 innocent processes: process `123` (`echo` argument) and process that happened to retake `echo` PID. – ZyX Sep 05 '14 at 15:03
-
My solution will fail in this case though (it will try to kill `{echoPID}=done:{lessPID}`). – ZyX Sep 05 '14 at 15:04