What's the difference between &! and &| in zsh?
Categories:
Understanding Zsh Job Control: &! vs. &|

Explore the subtle yet significant differences between &!
and &|
in Zsh for background job management and process control.
Zsh, the Z shell, is a powerful command-line interpreter that offers advanced features beyond traditional shells like Bash. Among its many capabilities, Zsh provides sophisticated job control mechanisms. When running commands in the background, you might encounter the operators &!
and &|
. While both relate to background execution, they serve distinct purposes, particularly concerning job control and process group management. Understanding these differences is crucial for effective scripting and interactive shell use.
The Basics of Backgrounding with &
Before diving into &!
and &|
, let's quickly review the standard &
operator. Appending &
to a command runs it in the background, detaching it from the current shell's foreground process. This allows you to continue using the shell while the background process executes. The shell typically prints a job number and the process ID (PID) for the background job.
sleep 10 &
[1] 12345
Running a simple sleep command in the background.
Understanding &!
(Disown and Background)
The &!
operator in Zsh is a combination of backgrounding a command and immediately disowning it. When a job is disowned, it is removed from the shell's job table. This means the shell will no longer track it, and it will not receive signals like SIGHUP
if the shell exits. This is particularly useful for long-running processes that you want to continue even after you close your terminal session, without explicitly using nohup
or disown
as a separate command.
flowchart TD A[Command] --> B{"Append `&!`"} B --> C[Execute in Background] C --> D[Remove from Shell Job Table] D --> E[Process Continues Independently] E --> F[Shell Exits (No SIGHUP)]
Flowchart illustrating the behavior of &!
.
sleep 30 &!
jobs
# Output: (no jobs listed, or only other active jobs)
Running sleep 30
with &!
and checking the job table.
&!
is a convenient shortcut for command &; disown
. It's ideal for processes you want to truly detach from your current shell session.Understanding &|
(Background with Job Control)
The &|
operator is less common and has a very specific use case related to job control and process groups. It runs a command in the background, but crucially, it places the command in its own process group. This is primarily relevant when you want to ensure that a background process is not affected by signals sent to the foreground process group (e.g., Ctrl+C
which sends SIGINT
to the foreground process group). However, it still remains in the shell's job table, unlike &!
.
flowchart TD A[Command] --> B{"Append `&|`"} B --> C[Execute in Background] C --> D[Place in New Process Group] D --> E[Remain in Shell Job Table] E --> F[Foreground Signals Don't Affect] F --> G[Shell Exits (SIGHUP Sent)]
Flowchart illustrating the behavior of &|
.
sleep 30 &|
jobs
# Output: [1] running sleep 30
Running sleep 30
with &|
and checking the job table.
&|
creates a new process group, it does not disown the job. If you close the terminal, the process will still receive SIGHUP
and likely terminate unless explicitly disowned or handled by nohup
.Key Differences and Use Cases
The primary distinction lies in job table management and signal handling upon shell exit. &!
is for complete detachment, while &|
is for process group isolation within the shell's job control. Most users will find &!
more generally useful for fire-and-forget background tasks.

Summary of differences between &!
and &|
.
In summary, choose &!
when you want a command to run in the background completely independently of your shell session, even after you close the terminal. Choose &|
when you need to isolate a background process into its own process group for signal handling purposes, but still want it managed by the shell's job control (e.g., fg
, bg
, jobs
). For most common backgrounding needs, &
or &!
will suffice.