Understanding Linux I/O Redirection: Combining stdout and stderr with >file 2>&1 &

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.txt is shorthand for 1>output.txt, redirecting stdout to a file.

  • 2>errors.log redirects only stderr.

  • 2>&1 means "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>&1 Is Preferred Over >log 2>log

    Consider 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.log
    
    

    In Variant A, the shell opens all.log once 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.log twice: 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 second 2>all.log can overwrite part of the first stream’s output — especially under high-volume or asynchronous I/O.

    Demonstration with Real Output

    Assume test.sh contains:

    #!/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 lines
    
    

    Background 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 to log even 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.

Tags: bash Linux shell-scripting io-redirection file-descriptors

Posted on Mon, 13 Jul 2026 16:28:26 +0000 by usawh