basically tech

70 Shell stuff: job control and screen

Monday 26th March, 2007

Now there is also tmux.
Rob. April 2015.

A look at using shell job control, plus a quick overview of what I consider to be the best alternative to job control, GNU screen.

run a task in the background

This is something many people know. To run a task in the background, just type the command, followed by a space and an ampersand and hit "enter":

$ mutt &

[1] 26749

This shows you that you have a job running in the background, and that it's process id is 26749.

(Note I wouldn't normally run mutt in the background; this is just an example.)

What this won't do is allow your task to continue running after you have logged out. In fact, if you try to log out (or exit your terminal), the shell will warn you that you have active tasks running:

$ exit

exit
There are stopped jobs.

[1]+  Stopped                 mutt

We know the process id, so we could just kill the job. But that's a bit messy. :) It's always best to shut these things down properly.

So now we need to get back to our background job so we can shut it down.

bring a task to the foreground

Well, we know that this is job [1]. So to switch to job [1], simply type:

$ %1

Then shut the application down normally.

bash shell specific: fg

If you use the bash shell (and possible some others), you can also use the more intuitive fg command.

$ fg 1

list jobs running in the background

If you don't know which job numbers were running in the background, you can use the command jobs to find out, e.g:

$ jobs

[1]+  Stopped                 mutt

The jobs manpage will reveal more about the meanings behind the output from running the command.

suspend a currently running task

If you wish to suspend a task which is currently running in the foreground, type <Ctrl>-z (hold down the Ctrl key and press "z" once). Note that this will suspend the task, not background it. To allow it to keep running in the background, you then need to type bg <job id> and hit the return key:

$ tar cjvf /backup/rob/home.tar.bz2 .

./
./bin/
./bin/doom3
...

<Ctrl>-z    (suspend the job, the shell returns)

[1]+  Stopped                 tar cjvf /backup/rob/home.tar.bz2 .

allow a suspended task to run in the background

$ bg 1    (allow job 1 to continue to run in the background)

[1]+ tar cjvf /backup/rob/home.tar.bz2 . &
$ ./bin/mutt.sh
./bin/url_handler.sh
./bin/bash_colours
...

Note that since I've opted for the verbose output from tar, once the job is allowed to run it continues to output to stdout.

By default, the bg command will background the last job you suspended, so in this example it's not strictly necessary to type the full bg 1, but it's probably a good habit to get into.

run a task in the background, and allow yourself to logout

If you want to run a job in the background, and want it to continue to run after you have logged out (an impromptu manual backup which takes a long while to run, perhaps), then nohup is one way of doing it.

nohup will run a command, allowing it to ignore hangup signals. It will not run in the background by default; that still requires you to put an ampersand at the end of the command.

$ nohup tar cjf /backup/rob/home.tar.bz2 . > /dev/null 2>&1 &

At first glance, this seems like a curious command. I've asked to run a tar backup of my home directory, ignoring hangup signals, in the background, but redirecting the output (stdout and stderr) to /dev/null. Why redirect the output to /dev/null?

If stdout is a terminal, then by default nohup redirects stdout and stderr to a file named nohup.out (in the current directory). If that can't be created, then it redirects to $HOME/nohup.out. If that can't be created, then the command is not run. So, unless you particularly need the data in nohup.out cluttering up your filesystem, redirect it to /dev/null, or at least to some other file with a name which makes more sense than nohup.out. Some development hosts I've administered have literally been littered with nohup.out files. Developers, eh?

One warning: if you run a command using nohup and put it in the background, and you then close the terminal or logout, you will not be able to access that task directly using the jobs/%25<N> commands. If you then want to stop the job before it has completed, kill becomes your only option.

bash shell specific: disown

If you use the bash shell, then you have an alternative (don't you always?) Instead of using nohup, just run the command normally, put it in the background one of the two ways we've discussed, and then disown -h the job.

$ tar cjf /backup/rob/home.tar.bz2 . &

[1] 32089

$ disown -h

You can then safely logout or close your terminal. As with nohup, if you close the terminal or logout, you will not be able to access that command directly using the jobs and %25<N> or fg <N> commands.

GNU screen

screen is great. If you are working on a host which has screen installed, then all that stuff about job control can be quietly ignored. Unfortunately, this is not always the case, especially with commercial Unices. In addition, you may have absent-mindedly kicked off a long-running job without having previously fired up screen first, and then those job control commands may come in useful!

The main problem with screen is that the initial learning curve is quite steep.

What I consider to be the main benefit of screen is that your programs and sessions are preserved, even if your terminal, or X, or your remote connection crashes. You can also detach from a screen session, and log out, leaving various programs running, and then login and re-attach to screen later to see how they're getting on.

This is not the place to write a tutorial on how to use screen; that's been done many times already (and I've listed a few of the tutorials at the end of this article), but here are a few of the more useful commands.

command effect
screen starts a new screen instance
<Ctrl>-a " list available windows
<Ctrl>-a c create a new window and switch to it
<Ctrl>-a n switch to the next window
<Ctrl>-a p switch to the previous window
<Ctrl>-a A rename the current window
<Ctrl>-a d detach screen from the current terminal (programs will continue to run)
<Ctrl>-a ? help; show key bindings
screen -ls list running screen instances
screen -r <screen instance> attach to a specific screen instance (usually of the format screen_PID.TTY.hostname)
screen -R attach to the first detached screen instance available (it may not be the one you want, if you have more than one running!)

Note that all the <Ctrl>-a * commands are run from within screen.

To completely shut down the screen instance you're in, shut down all running programs and exit from the shells presented. When the final shell closes and you've been dropped back into your original terminal, you will have exited from (shut down) screen.

GNU screen links

TIP Using screen - Gentoo Linux Wiki
As you might expect, the Gentoo dudes have got some excellent documentation on this subject.

GNU Screen - Jonathan McPherson
Another good resource. (This guy's vim documentation is very good too.)

A Guide to Efficiently Using Irssi and Screen :: f0rked.com
A nice little section on screen, and you get to learn about irssi as well! Bargain!

Home