BashItOut

Ampersands & on the command line

In Bash, on the Linux command line, & is a control operator. It’s a shell builtin meaning it’s literally a core part of the Bash tool set.

It crops up in 2 main forms, as a single ampersand & and as a double ampersand &&.


Single Ampersand

A single ampersand & can often be found at the end of a command.

./myscript.py &

This trailing ampersand directs the shell to run the command in the background, that is, it is forked and run in a separate sub-shell, as a job, asynchronously. The shell will immediately return the return status of 0 for true and continue as normal, either processing further commands in a script or returning the cursor focus back to the user in a Linux terminal.

The shell will print out the forked process’s job number and process ID (PID) like so:

$ ./myscript.py &
[1] 1337

The stdout of the forked process will still be attached to the parent, so any output will still appear in your terminal.


After a process is forked using a single trailing ampersand &, its process ID (PID) is stored in a special variable $!. This can be used later to refer to the process:

$ echo $!
1337

Once a process is forked, it can be seen in the jobs list:

$ jobs
[1]+  Running                 ./myscript.py &

And it can be brought back to the command line before it finishes with the foreground command:

fg

The foreground command takes an optional argument of the job number, if you have forked multiple processes.


A single ampersand & can also delimit a list of commands to be run asynchronously.

./script.py & ./script2.py & ./script3.py & 

In this example, all 3 python scripts are run at the same time, in separate sub-shells. Their stdout will still be attached to the parent shell, so if running this from a Linux terminal, you will still see the outputs.

This can also be used as a quick hack to take advantage of multiple cores with shell scripts, but be warned, it is a hack!


To detach a process completely from the shell, you may want to pipe the stdout and stderr to a file or to /dev/null. A nice way of doing this is with the nohup command.

Double Ampersand

A double ampersand && in Bash means AND and can be used to separate a list of commands to be run sequentially.

Commands separated by a double ampersand && are to be run synchronously, with each one running only if the last did not fail (a fail is interpreted as returning a non-zero return status).

This can be especially handy for when you have a couple of commands to run, but you don’t want the second to be run if the first fails.


Let’s look at a trivial example:

cd /root/ && echo "I've got root"

This is actually 2 commands. A cd and an echo.

The cd command will run first and attempt to change to the /root/ directory. If successful, it will continue to echo “I’ve got root”.

If the cd command fails and you can’t access the /root/ directory, the shell will stop execution and the echo command will not be run.

Now let’s break down another example (split onto separate lines with a backslash for formatting):

cd /tmp/files/ \
&& tar zcvf files.tgz * \
&& rsync -avz files.tgz example.com:/tmp/

Here we have 3 commands.

Go to a directory:

cd /tmp/files/

Tar up the files:

tar zcvf files.tgz *

And rsync the tarball up to a server:

rsync -avz files.tgz example.com:/tmp/

If cding to the directory /tmp/files/ fails (e.g. it does not exist or we don’t have permission to access it), we don’t want to attempt the tar command as that will tar up the files in our current directory.

Likewise, if the tar command fails for some reason, it would not make sense to try to rsync the output to our server.

This example is fairly trivial, but there are many uses were it makes sense to chain some commands together in a more fails-safe way like this.


Ampersands can also be escaped if you don’t want to use the special functionality. To do this, just prefix it with a backslash:

echo Tom \& Jerry

Tags: Linux

blog comments powered by Disqus

About

@MTerzza Twitter Icon

+MikeTerzza Google Plus Icon

Atom | RSS RSS Icon

Recent Posts:

RTL SDR Frequency Drift Offset

Random Seriousness with Python and Password Generation

Random Fun and the Busy Linux Geek

Ampersands & on the command line

Killing processes in Linux