Job
control isn't always a good thing. For instance, I might want to start a long
equipment-monitoring job running when I go home for the night. But if I simply
put the job in the background and try to log out, zsh says zsh: you have running
jobs
. If I log out anyway, the shell sends my
background job a HUP signal. I could use nohup
(Section 23.10) to block the
hangup signal, but there's a simpler way: tell the shell, "Don't use job control
on this job." This is also true of jobs that I know are there — a clock running
on my X Window System display, for instance — and that I'll never want to use
job control on, so the jobs are just cluttering the jobs (Section 23.3)
list.
To run a job without job control, the trick in most shells is to start the job
in a subshell (Section 43.7), and put the job inside
that subshell into the background. This is sometimes called "disowning" the job.
Note that the ampersand (&
) is
inside the parentheses:
% (myprog -opts &)
The job won't appear in the jobs list, but ps ( Section 24.5) should show it running. (You might need to use a "show all jobs" option like ps -x or ps -e.) If you use ps -l for a "long" listing, you'll see that the process' PPID (the process ID number of the parent process (Section 24.3)) is 1; this means that the process is now "owned" by init (Section 24.2). On the other hand, if you'd started the job in the background normally (without the subshell trick), you'd see that its PPID was that of the shell you started it from.
The Z shell
has a more direct way: its &!
and
&|
background operators. Both of them
do the same thing: if you use one of those operators instead of plain &
, the job will be disowned immediately; it
won't appear in the jobs list.
In most shells, once you start a job without the subshell trick, the shell that started the job will continue to be its parent. (Some shells, like the C shells, will give up ownership of a child process and let it keep running when you end the shell — that is, when you log out — and then init will "inherit" the process.) In zsh and bash Version 2, though, you can change your mind after you start a job by using the shell's built-in disown command. Give disown the job number you want the shell to "forget." For instance, I'll start a background job and then disown it. It disappears from the job table, but giving ps its process ID shows that the job is still running:
zsh%myprog -opts&
[1] 28954 zsh%jobs
[1] + running myprog -opts zsh%disown %1
zsh%jobs
zsh%ps 28954
PID TTY STAT TIME COMMAND 28954 pts/5 S 0:09 myprog -opts
If you don't give a job number, disown
"forgets" the current job. The bash2 version
of disown has options that zsh doesn't: disown -a
disowns all jobs, and disown -r
disowns only running
jobs.
The
bash2 option -h
does a
different job: instead of removing a job from the job table, the job won't
receive any HUP signal sent to the shell. This is similar to what the nohup command does.
— JP