Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Lists and asynchronous commands

A list is a sequence of and-or lists separated by semicolons (;) or ampersands (&). Lists let you write multiple commands on a single line, and control whether they run synchronously or asynchronously.

Synchronous commands

When an and-or list is separated by a semicolon (;), it runs synchronously: the shell waits for the command to finish before running the next one.

$ echo "First command"; echo "Second command";
First command
Second command

The semicolon can be omitted after the last command:

$ echo "First command"; echo "Second command"
First command
Second command

Asynchronous commands

When an and-or list is separated by an ampersand (&), it runs asynchronously: the shell does not wait for the command to finish before running the next one.

$ echo "First async command" & echo "Second async command" & echo "Synchronous command"
Second async command
Synchronous command
First async command

Here, the commands run in parallel, so their output may appear in any order.

In an interactive shell, starting an asynchronous command prints its job number and process ID:

$ echo "Async command" &
[1] 12345
Async command

Because the shell does not wait for asynchronous commands, they may keep running while the shell reads new commands or even after the shell exits. To wait for them to finish, use the wait utility (see below).

Input redirection

By default, an asynchronous command’s standard input is redirected to /dev/null to prevent it from interfering with synchronous commands that read from standard input. This does not apply in job-controlling shells.

$ echo Input | {
>     cat &
>     read -r line
>     echo "Read line: $line"
> }
Read line: Input

In this example, the asynchronous cat reads from /dev/null, while read reads from standard input.

The ! special parameter

The ! special parameter gives the process ID of the last asynchronous command started in the shell. This is useful for tracking or waiting for background jobs.

The wait utility

The wait utility waits for asynchronous commands to finish. With no operands, it waits for all asynchronous commands started in the current shell. With operands, it waits for the specified process IDs.

$ mkdir $$ && cd $$ || exit
$ echo "Async command" > async.txt &
$ echo "Synchronous command"
Synchronous command
$ wait $!
$ cat async.txt
Async command

Here, the shell starts an asynchronous command that writes to a file. wait $! waits for it to finish before reading the file.

Job control

In yash-rs, all asynchronous commands start as background jobs. If the monitor shell option is enabled, you can use job control commands to manage these jobs.