Skip to content
Latchkey

tee: Usage, Options & Common CI Errors

tee splits a stream: it passes data through while also saving a copy to a file.

tee lets you log output and keep it flowing down the pipe. In CI it is the trick for writing root-owned files (sudo tee) and the reason a pipeline can hide a failing command exit code.

What it does

tee reads stdin and writes it to both stdout and one or more files. It is used to capture build logs while still displaying them, and to write files that need elevated permissions.

Common usage

Terminal
make build 2>&1 | tee build.log
echo "deb ..." | sudo tee /etc/apt/sources.list.d/x.list
some_cmd | tee -a run.log          # append
echo "127.0.0.1 host" | sudo tee -a /etc/hosts
cmd | tee out.txt | grep ERROR

Options

FlagWhat it does
-a / --appendAppend to files instead of overwriting
-i / --ignore-interruptsIgnore SIGINT
(sudo) teeWrite a file as root from a non-root pipe

Common errors in CI

The big gotcha: cmd | tee log.txt exits with tee's status, not cmd's - a failing build can look green because tee succeeded. Use set -o pipefail so the pipeline reflects cmd's failure (or check ${PIPESTATUS[0]} in bash). "tee: /etc/...: Permission denied" means you piped into a privileged path without sudo tee. Appending without -a truncates the file each run.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →