Print View

Job Control
Created: 01/25/2007


General Information

Sometimes processes can take time to complete, thus tying up your console session.  What if you want to run multiple processes in the background on the same shell session?  With the built-in job control, you can.  There are three main conditions a job can be in: Running, Stopped/Suspended, or Terminated.  To control them, we'll use the fg and bg commands.

Requirements

  1. A SSH client such as puTTy or SecureCRT (if you aren't on the box).

Usage

If there is a process that you know will take a while to complete and would like it to be forked to the background immediately, you can append a & at the end of the command to achieve this.  For this example, we'll just create a simple timer.
$ sleep 100 &
[1] 45862
$
As you can see the command prompt was returned after displaying two important numbers.  The first number [1] is the job number which is used by other job control commands to reference it.  The second number 45862 is the process ID that the system assigns.  So, the job number is unique to the shell and the process ID is unique to the operating system.   If you forget what job number you want to reference, you can always see a list of all the jobs in the job controller:
$ jobs
[1]+  Running                 sleep 100 &
$
Here you can see that the original job is in the Running state.  Now, if you want to bring it to the foreground, you can use the fg command:
$ fg 1
sleep 100

Now, if you have a job running in the foreground and you want to send it to the background, you can hit control-z to suspend or stop the job.  This will return the command prompt.
$ fg 1
sleep 100
^Z
[1]+  Stopped                 sleep 100
$
You can now continue the job in the background with the bg command:
$ bg 1
[1]+ sleep 100 &
$
So, now you have a job running in the background and you want to kill it.  Well, you can either bring it to the foreground and interrupt it with control-c, kill the process ID, or kill the job number.  Here I'm going to kill the process using the job number:
$ kill %1
[1]+  Terminated: 15          sleep 100
$
Now you can see the job is terminated.

Note:  When jobs are running in the background, they may still send their output to the terminal.  To disable the output, send it to > /dev/null:
$ portsnap fetch update > /dev/null &


Author: Jon LaBass
jon at bsdguides dot org

Find this guide useful?
Support the author:


4 Comments

Posted by rhyous on January 28, 2007 at 11:04:57 pm EET

One thing to note is the things running in the background are not terminated when the shell closes.

Lets say are connected remotely via ssh.

If you run a command in the foreground:

$ sleep 500

Then close the shell, the task is terminated.  

Connect again with ssh and use:

$ ps -ax |grep sleep

Which will verify that the task is not running.

However, if you run it in the background:

# sleep 500 &

Then close the ssh session, the task continues to run.  Once again connect in with a new ssh session.

This is beneficial if you want to do something that takes a long time and you want to connect remotely, start the task, then disconnect.  Before I learned this, I would always be frustrated because I would start a portinstall on my own box from work, so whatever port would be installed when I got home.  However, my computer would go to sleep and the ssh session would time out, killing the task.  Obviously I start it in the background now and close the ssh session immediately.


Posted by bramey on February 13, 2007 at 6:02:02 pm EET

Great guide!  Very useful.  I knew about stopping jobs and bringing them back to the foreground with fg, but I didn't know that its sister bg also existed.

I've had one problem.  I'm developing a small web-app at work using the Catalyst MVC framework for Perl.  It comes with a little development server that's a Perl script I run in the background.  I send output to /dev/null, so the full command looks like this: "script/server.pl > /dev/null &", but it still sends output to the terminal.  Any ideas on why?  Obviously, sending output to /dev/null works with any other processes, but not with this one and I don't know why it would be any different.


Posted by Jon on February 14, 2007 at 8:34:08 am EET

I suspect you are seeing the output of stderr which goes to the terminal.  Try the following to redirect stderr to stdout (in this case /dev/null):

script/server.pl > /dev/null 2>&1 &


Posted by bramey on February 15, 2007 at 5:02:22 pm EET

That did it.  Thanks!  


Copyright 2003 - 2010 BSD Guides.  All rights reserved.

About | Terms of Use | Privacy | Contact