Bash Job Control

You may think you can do only one thing at a time in Bash. This notion seems plausible – you have exactly one command prompt, so how should you run different commands at the same time? However, this notion is wrong. Bash offers a set of built-in multitasking features called Job Control.

Why you want to use it

Suppose you are working in Vim when suddenly you need to look up something in a man page. What do you do?

You could save the file you are working on, close Vim, check the man page, open the file in Vim again, navigate back to the line you edited last, and finally continue your work (now having already forgotten what you read in the man page) … Alternatively, in a graphical desktop environment, you could open another terminal window and check the man page there, but this is an equally awkward interruption of your workflow. Or if you spend much time on the command line you are possibly in a tmux session already so you could simply split your terminal window to open the man page. (The last option is actually a real alternative to using Job Control since tmux offers a boatload of other useful features. However, in some situations it is just plain overkill to use tmux.)

Leveraging Job Control you would do this: Press Ctrl-Z to suspend Vim, check the man page, and type fg to get back to your Vim session which is waiting for you in exactly the state you left it. Try it now!

How it works

The commands available for Job Control are Ctrl-Z, jobs, fg, bg and the & operator.

Ctrl-Z suspends the currently running process (be it an interactive program like Vim or htop or a long running command like a wget download) and gives you a new command prompt. To get back to the suspended process and continue it in the foreground type fg.

A suspended process will be interrupted and by default won’t continue running in the background. This is okay for interactive programs but less so for long running commands that should silently continue their work in the background without cluttering up your shell prompt. Here the bg command is what you want: While fg continues a suspended job in the foreground (i.e., it puts it back at your shell prompt) bg makes a suspended job continue running invisibly in the background.

If you know up front that a command you are about to issue will run for a long time you can take a shortcut to schedule it for background execution; instead of suspending the command with Ctrl-Z and sending it to the background with bg you can just append the & operator to the command which sends it directly to the background:

$ wget http://example.org/some-large-file &

When you are juggling with several jobs use the jobs command to get a list of all running and suspended commands:

$ jobs
[1]+ Stopped vim foo
[2]  Stopped man bash
[3]- Running wget http://example.org/some-large-file &

By default, the fg and bg commands continue the last suspended job (which is marked by the + sign in the output above). To specify another job from the list returned by the jobs command give its job number or (if this is unambiguous) the job’s command name to the fg or bg command. The following three commands are all equivalent given the job list above:

$ fg
$ fg 1
$ fg vim