When you press Ctrl+Z in a terminal, this causes the foreground process group to receive the signal SIGTSTP (assuming the terminal is in cooked mode and the default key bindings are in place). If the process hasn't set a signal handler for SIGTSTP, this causes the process to be suspended (and even if the process has set a signal handler, it usually only does a small amount of processing before suspending itself). When a process is killed, suspended or resumed, its parent is notified via a SIGCHLD signal; this is what causes the shell to display a new prompt and maybe a message like [1] + 1234 suspended foo
. The information flow is
key → suspension → shell
and not
key → shell → suspension
so you can't configure a different reaction for Ctrl+Z.
You can set a trap for SIGCHLD, but the trap is not executed when the job is the current foreground job. For the most part, this means that the trap is executed only when a background job terminates, not when the foreground job terminates. But it also means that you can't react to the suspension of the foreground job.
You can indirectly react to changes in background jobs by setting a precmd
hook that compares the job states with states saved from the previous precmd
run. But I don't know what you could do with that: there can only be a single suspend key, so you need some extra information to know whether the process was meant to be paused, backgrounded or disowned.
I've set up zsh so that pressing Ctrl+Z at an empty prompt backgrounds the current job. This lets me press Ctrl+Z twice to put the foreground job into the background with only a short suspension.
fancy-ctrl-z () {
if [[ $#BUFFER -eq 0 ]]; then
bg
zle redisplay
else
zle push-input
fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z
You could make it call disown
if you like. Or you could arrange for a third Ctrl+Z to call disown
with the following untested modification.
fancy-ctrl-z () {
if [[ $#BUFFER -eq 0 ]]; then
if (($fancy_ctrl_z_already_bg)); then
disown
else
bg
fancy_ctrl_z_already_bg=1
fi
zle redisplay
else
zle push-input
fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z
fancy_ctrl_z_precmd () {
fancy_ctrl_z_already_bg=0
}
precmd_functions+=fancy_ctrl_z_precmd
bg
+disown
instead ofkill -CONT -1234
.alias dr='disown -r'
in bash.bg
anddr
do the trick.