You know all about multitasking on the desktop, but some Linux users aren't aware that you can do exactly the same kind of things in the console, albeit with a little more hands on control. In this article we'll run through the basics of job control in Linux.
In a graphical environment, such as your window manager, you can run multiple console tasks at once simply by opening more terminal emulators (such as xterm, aterm, etc). If you're stuck with just the single terminal, or you just don't want to clutter your desktop with a lot of windows, then you need to control the running of console programs.
Foreground vs Background
When you start a program normally in the console it runs in the foreground. Foreground programs have access to the standard input stream, allowing them to receive commands from the user, and the standard output stream, allowing them to print information back to the user.
Programs running in the background do not have access to these streams, which means they cannot interact with the user, but are unchanged otherwise. If your task doesn't require that kind of input and output, then you can run it in the background and continue to use the console as normal.
Examples of jobs that are often run in the background are long operations that do not require input, such as compiling or building software, or programs that interact with the user through a GUI and not the console.
You can start any program in the background by adding a "&" character to the end of the line. For example if we were starting Firefox in the console we'd write:
$ firefox &  936 $
Firefox starts and control of the terminal is returned immediately. You can see that two numbers are printed in the console. The first, between the brackets, is the job number, which can be used to control the job. The second is the Pid (process identifier), which is a unique, system wide identifier for the process.
You can also suspend an already running process by hitting CTRL-Z during it's operation. For example, if we were to load vim, and then hit CTRL-Z we'd see the following:
$ vim + Stopped vim $
Again the job number is printed, as well as the program name. Suspending a program does not make it run in the background, rather it stops the process in place, ready to be resumed at the users command.
Restarting suspended processes
You can restart a process either in the foreground or in the background.
To restart a process in the foreground, use the command fg followed by the job number.
$ vim + Stopped vim $ fg 1 vim
This example will load vim, then after we hit CTRL-Z will suspend it, the fg command starts it running again in the foreground, bringing up the vim console window.
Likewise, you can restart a process in the background using the bg command. In the following example we start an xterm in the foreground. This blocks our console as it has claimed the input and output. When we hit CTRL-Z the process is suspended, which gives us the console back but does not allow us to type into the new terminal. By typing bg 1, we run the xterm in the background — making both terminals available:
$ xterm + Stopped xterm $ bg 1 + xterm & $ + Done xterm
When we close the xterm window the process exits, and the Done message is printed in our original prompt to let us know. Be careful, as this can interfere with the output of other programs you run in the original terminal.
Examining and removing current jobs
To take a look at what jobs are currently running, run the jobs program:
$ jobs + Stopped vim - Running xterm &
This shows us that there are two programs running, job 1 is vim, which is suspended. Job 2 is xterm which is running in the background. With this information we can move either into the foreground or background with fg and bg.
To kill a job we use the appropriately titled program kill. Usually kill is used with a process identifier — the same as was printed when we started the program with "&". The process identifiers of all running processes can be found by using the ps command:
$ ps PID TTY TIME CMD 1260 pts/0 00:00:00 bash 1537 pts/0 00:00:00 vim 1672 pts/0 00:00:00 xterm 1690 pts/0 00:00:00 ps
This shows the four programs we have running in this console: the shell (in this case bash), our two programs, vim and xterm and the ps command we just ran. We can kill any of these processes by typing kill followed by the process identifier:
$ kill 1672 $
And the xterm window disappears.
Finding and typing out the process identifier is often more of a hassle than you want at any given moment, but if you know the job number there is a quicker way. You can replace the process identifier in the previous example with the job number preceded by a "%" character:
$ kill %1 + Stopped vim
The program may not be killed immediately if it is suspended, but should exit as soon as it becomes active — either in the foreground or background. You can avoid this by telling the kill program to force the program to end using the -9 flag:
$ kill -9 %1 $
Be careful with this flag however, forcing too many programs to close can leave your system unstable, since they are not given a chance to clean up after themselves.
While the ubiquity of graphical desktops have made job control not quite so vital a skill for UNIX and Linux users, learning how to manage jobs in your terminal can make your workspace neater and make you more productive. Are there more tips in this area that I've left out? Share your knowledge with the community by posting below.