Running commands in the background using &

Since Linux is a multitasking operating system, we can run any command in the background at any time.

Let us run the ls command in the background with:

ls & 
            

Clearly it's not going to make too much sense as the ls command completes so quickly that putting it in the background will have little effect. Despite this, if we run the command, it prints the job number first with the process id (PID) thereafter.

[riaan@debian] ~$ ls &
[1] 7276
            

Every job in Linux gets a process id (PID).

So let us look at using background processing in a more useful example. We might say:

find / -name "hamish" 2>/dev/null &
            

This would give us a job number and the process id. We could now say:

echo $!
            

That would give us the process id of the most recently run command. So we could save the PID in a variable:

mypid=$!
            

If we decided to kill the process, it's as simple as:

kill -9 $mypid
            

One place that this logic is frequently used is to make a run file. A run file is a file that keeps a copy of a shell scripts PID, and can check against this run-file to determine whether the script has finished.

In other words while your script is running you want to keep a copy of the process id, and as soon as it exits, you will delete the run file.

To illustrate this point:

#!/bin/bash
echo $! > /var/run/myscript.pid
            

keeps a copy of the process id in a file called myscript.pid (in the directory /var/run). At a later stage, if I need to test whether the script is running, or I need to kill it, all I need do is:

kill `cat /var/run/myscript.pid`
            

Another useful place to use the PID of the previous command is if you want to wait for one process to complete before beginning the next.

How do we force the script to wait for a command to complete? A shell built-in command called the wait command allows this:

cmd1
cmd2
wait
...
            

will wait for the command cmd2 to complete before proceeding. More explicitly:

cmd1
CMD1_PID=$!
...
...
wait $CMD1_PID
cmd2
            

This will force the shell for wait for cmd1 to complete before we begin cmd2.

We are able to control the speed (to a limited extent) with which our scripts execute by using the wait command. Consider the code snippet below.

#!/bin/bash
ping -c 10 192.168.0.1 2>/dev/null 1>&2 &
PING_1_PID=$!			#gets process id of previous ping
wait $PING_1_PID			#wait for the ping process to complete
echo "Ping complete"		#inform user
ping -c 10 192.168.0.2 2>/dev/null 1>&2 &	#start again ... 
            

In line 2, ping will send ten ICMP packets to 192.168.0.1, redirecting both stderr and stdout to /dev/null and running all this in the background.

We store the PID of this ping in a variable PING_1_ID, then telling the script to wait for this process to complete before starting the next process.