Super User is a question and answer site for computer enthusiasts and power users. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I follow this pattern of suspending the task and then letting it to continue too often with the Ctrl-Z bg sequence.

I was wondering is there any way to compress that to single keypress?

My shell is zsh

share|improve this question
I want to say that is probably hard coded. But I am not 100% – hydroparadise Jan 13 '12 at 14:18
Sure it is, but I've found the elegant solution, thank you – Evgeniy Dolzhenko Jan 13 '12 at 14:38
up vote 17 down vote accepted

The Ctrl+Z sequence is handled by the terminal, not by the shell. (Useful background: What is the exact difference between a 'terminal', a 'shell', a 'tty' and a 'console'?)

Only a small, non-extensible set of functions can be bound to a key in a terminal. You can customize the keys bound to these functions but not add another function. These functions fall into three categories:

  • Command line edition in programs that don't provide their own (canonical mode, also called cooked mode (by opposition with raw mode), which you'll rarely use in practice): end of file (eof, Ctrl+D), end of line (eol, Ctrl+M), erase character left (erase, Ctrl+H), erase word left (werase, Ctrl+W), erase line (kill, Ctrl+U).
  • Manual flow control: stop (Ctrl+S), start (Ctrl+Q). Only useful on old serial terminals that dropped characters when the terminal couldn't keep up with the computer or vice versa.
  • Signalling: interrupt (intr, Ctrl+C), force quit (quit, Ctrl+\), suspend (Ctrl+Z).

Some systems, including Linux, extend that list, but I've never seen one that included backgrounding. Note that it would take support both in the terminal driver in the kernel, and in the terminal emulator. So you have to make do with suspend, which sends the foreground job a SIGTSTP signal. This triggers a SIGCHLD in the parent process of the foreground job's leader, which is usually the shell. When the shell received SIGCHLD, it calls waitpid to figure out why it was notified, and upon detection that a background job was suspended, it displays a notification (e.g. [1] + 12345 suspended mycommand) and a new prompt.

You could program the shell to send a SIGCONT signal to the foreground job. I don't think zsh has a hook for that, you'd need to patch the source code. And there's no way for zsh to know whether you really meant to interrupt the program (oops, this program may be doing the wrong thing, let me suspend it while I sort it out) or to background it.

What I do is to set the Ctrl+Z key sequence in zsh to background the current job (%%). That way, I can send the foreground job to the background by pressing Ctrl+Z Ctrl+Z. While I'm at it, I make Ctrl+Z do something else useful when the current input line is not empty (so I haven't just come back from a subprocess): “suspend” the current input line, allowing me to type another command, after which the interrupted line is pushed back into the input buffer.

fancy-ctrl-z () {
  if [[ $#BUFFER -eq 0 ]]; then
    zle redisplay
    zle push-input
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z
share|improve this answer
Gilles, this is an incredibly complete, educating and thoughtful answer I couldn't expect to get! Thank you so much! – Evgeniy Dolzhenko Jan 16 '12 at 15:28

So found the solution, not exactly what I want but darn close from here

On an empty command line runs bg (so that Ctrl+Z Ctrl+Z suspends a program and immediately resumes it in the background).

share|improve this answer
I will note that this requires zsh; it is not supported in bash. (out of the box, anyway) – Kevin M Jan 13 '12 at 16:55
@KevinM You can write an analogous function in bash (at least the basic version making Ctrl+Z call bg, I'm not sure about detecting a non-empty input line). – Gilles Jan 13 '12 at 19:22

Are these commands that you wanted to run in the foreground initially, and then switch to the background? I don't know if there's a simpler way to do that. But if you'd like to run commands that will be in the background to begin with, you can just add an ampersand to the end of the line. e.g., ping & will start pinging in the background; you won't be able to interact with it unless you type fg.

share|improve this answer
Thanks, the problem is that sometimes you don't have an idea of how much time running the command would take, so you run interactively and then realize you better let it continue on background. The accepted answer works wonders for me, using it daily! – Evgeniy Dolzhenko Feb 29 '12 at 11:34
Thanks for the response. The accepted answer is pretty neat! – octern Mar 1 '12 at 19:23

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .