Skip to content
shellmap

Attach to the output of a running process

Read the stdout/stderr of an already-running process you did not launch — for debugging daemons, observing what a frozen-looking job is doing, and tailing logs that weren't redirected at start.

How to attach to the output of a running process in each shell

Bashunix
sudo strace -p 12345 -s 1000 -e trace=write

`-s 1000` = show up to 1000 bytes per call (default 32). `-e trace=write` filters to write syscalls only. Linux only. Requires CAP_SYS_PTRACE — sudo or `setcap cap_sys_ptrace=eip /usr/bin/strace`. Ubuntu disables ptrace by default; `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope` enables.

Zshunix
sudo strace -p 12345 -s 1000 -e trace=write
Fishunix
sudo strace -p 12345 -s 1000 -e trace=write
PowerShellwindows
Get-CimInstance Win32_Process -Filter "ProcessId = 12345" | Select CommandLine, ExecutablePath

Windows has NO equivalent to `strace -p` for normal user — needs ETW providers (`logman create trace …`) or DTrace-for-Windows. For pwsh's OWN background output: `Start-Transcript` before launching, then tail the transcript file.

cmd.exewindows
powershell -NoProfile -Command "Get-CimInstance Win32_Process -Filter 'ProcessId = 12345' | Select CommandLine"

cmd has no native introspection. Shell out to pwsh. Or use SysInternals Process Monitor (`procmon.exe`) — captures all file/registry/network events including stdout writes, GUI-based filtering.

Equivalents listed for Bash, Zsh, Fish, PowerShell, cmd.exe.

Gotchas & notes

  • **The hard truth: this is the hardest task on this site** — attaching to output of a process you didn't launch is fundamentally restricted by OS security. On Linux, `strace -p PID -e write -s 9999` shows every `write()` syscall the process makes (which includes stdout/stderr) — but you only see new writes, not buffered backlog, and the format is `write(1, "actual text", 11) = 11` (you must parse out the quoted strings). It DOES NOT show stdout that was redirected to a file; for that, `tail -f /proc/PID/fd/1` (Linux only — `/proc/PID/fd/N` are symlinks to the open files, and 1 is stdout). If stdout went to a pipe, `/proc/PID/fd/1` symlinks to `pipe:[INODE]` and is not readable.
  • **`reptyr` is the closest tool to "give me a real terminal for that running process"** (`apt install reptyr`). It detaches the process from its current terminal and reattaches to YOUR terminal — input + output both work. Requires the same ptrace privileges as strace. CAVEATS: programs with deep tty handling (vim, less, mosh) often break on reattach because they cached the original terminal's dimensions and capabilities; new SIGWINCH may not propagate cleanly. Best for daemons that just print to stdout (build scripts, long-running aggregators). Closest macOS / BSD equivalent: NONE (lack of /proc + SIP restrictions make this nearly impossible without disabling SIP).
  • **macOS SIP prevents most introspection**: `dtruss` (DTrace) requires SIP off (`csrutil disable` from Recovery mode — DANGEROUS, off-by-default in modern macOS). `sample -file PID 10` is the SIP-friendly partial answer (samples stack traces for 10 seconds — useful for "what is this process doing right now" but doesn't capture stdout). `lldb -p PID` attaches a debugger; printing variables works but stdout is still the original tty. Practical advice on macOS: if you might need to inspect output later, redirect to a file at launch time (`./cmd 2>&1 | tee output.log` or `./cmd >> output.log 2>&1`); retrofitting introspection is hard.
  • **Windows: ETW (Event Tracing for Windows) is the underlying primitive**: every process emits ETW events; `logman.exe` configures providers; `pwsh wpr.exe` (Windows Performance Recorder) captures. Sysinternals **Process Monitor** (`procmon.exe`) wraps this with GUI: filter on PID, watch every file/registry/network operation including stdout writes to console (CONOUT$). For a single console process showing live output, the SysInternals **DebugView** (`dbgview.exe`) captures OutputDebugString calls — useful for apps that use `OutputDebugString` for trace logging. Powershell jobs (`Start-Job` / `Start-ThreadJob`) maintain their own output buffer — `Receive-Job -Keep $job` streams output without removing it.
  • **The right answer is usually "redirect at launch"**: every problem in this page exists because the process didn't redirect stdout/stderr to a known file when it started. Production daemons should: launch with `cmd >>/var/log/cmd.log 2>&1 &` or use systemd's `StandardOutput=file:/path/to/log`; one-off scripts run in `tmux` (output is in tmux's scrollback buffer, accessible via `tmux capture-pane -p`); pwsh jobs/scripts use `Start-Transcript` from the start. Retrofitting attach-to-output is a sign that something upstream went wrong — the next iteration of that script/daemon should pre-redirect. Fix the systemic issue, don't become an expert in strace tricks.

Related commands

Related tasks