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
- bring a task to the foreground
- list jobs running in the background
- suspend a currently running task
- allow a suspended task to run in the background
- run a task in the background, and allow yourself to logout
- 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!