The syntax command >file 2>&1 & is a common yet frequently misunderstood shell construct. It performs three distinct operations in one line: output redirection, error stream merging, and background execution.
File Descriptors and Stream Behavior
Every process in Linux starts with three default file descriptors:
- 0 (stdin): Input source — typically the terminal keyboard.
- 1 (stdout): Normal output destination — defaults to the terminal.
- 2 (stderr): Error message destination — also defaults to the terminal, but is separate from stdout for robustness.
Redirection operators manipulate where these streams point. For example:
-
>output.txtis shorthand for1>output.txt, redirecting stdout to a file. -
2>errors.logredirects only stderr. -
2>&1means "redirect file descriptor 2 (stderr) to wherever file descriptor 1 (stdout) currently points." Crucially, this is a reference-based redirection, not a duplication of the target file. ### Why>log 2>&1Is Preferred Over>log 2>logConsider two equivalent-looking variants:
# Variant A: Safe and efficient my_script.sh >all.log 2>&1 # Variant B: Risky and inefficient my_script.sh >all.log 2>all.logIn Variant A, the shell opens
all.logonce for writing (via>all.log), and then makes stderr share that same open file description. Both streams write sequentially to the same file handle — no race conditions or truncation.In Variant B, the shell opens
all.logtwice: once for stdout, once for stderr. Each open call creates an independent file offset. Concurrent writes may interleave unpredictably, and if the file is opened with truncation (default for>), the second2>all.logcan overwrite part of the first stream’s output — especially under high-volume or asynchronous I/O.Demonstration with Real Output
Assume
test.shcontains:#!/bin/bash echo "Operation succeeded" invalid_command_here echo "Continuing..."Running it with different redirections yields:
# Only stdout captured $ ./test.sh >out.txt ./test.sh: line 3: invalid_command_here: command not found # Both streams merged into one file (safe) $ ./test.sh >merged.txt 2>&1 $ cat merged.txt Operation succeeded ./test.sh: line 3: invalid_command_here: command not found Continuing... # Unreliable interleaving (avoid this) $ ./test.sh >unsafe.txt 2>unsafe.txt $ cat unsafe.txt # May show partial or garbled linesBackground Execution with
&The trailing
&detaches the command from the current shell session. It runs asynchronously, allowing immediate reuse of the terminal. Note that background jobs inherit the redirected streams — so./test.sh >log 2>&1 &writes all output tologeven when detached.Prcatical Use Case
A robust log-and-forget pattern for long-running services:
# Logs both success messages and errors to service.log, runs in background nohup python3 server.py >service.log 2>&1 &This ensures completeness, avoids file corruption, and decouples execution from the controlling terminal.