Частый кейс: запускаешь задачу (деплой, миграция, билд) и хочешь одновременно видеть вывод в терминале и сохранять его в файл. Обычный редирект
> убирает вывод из консоли. Решается через tee.Команда:
command 2>&1 | tee output.log
Что происходит:
2>&1 объединяет stderr и stdout; tee дублирует поток — пишет в файл и выводит в терминал.Добавление в файл (
append):command 2>&1 | tee -a output.log
Без потери кода возврата (важно для скриптов):
set -o pipefail
command 2>&1 | tee output.log
echo $?
Без
pipefail код возврата будет от tee, а не от command. echo $? нужно вызывать сразу после пайплайна, иначе значение перезапишется.Альтернатива:
command 2>&1 | tee output.log
exit ${PIPESTATUS[0]}
Важно:
PIPESTATUS нужно читать сразу после пайплайна, иначе он перезапишется.Пример: деплой
set -o pipefail
./deploy.sh 2>&1 | tee deploy.log
Лог сохраняется, при этом видно всё в реальном времени.
Пример: долгий билд
make -j4 2>&1 | tee build.log
stderr не теряется, но порядок строк может перемешиваться (из-за параллельности и буферизации).Разделение потоков с сохранением,
stdout в файл, stderr отдельно:command > >(tee out.log) 2> >(tee err.log >&2)
Используется process substitution (bash).
stdout/stderr остаются в консоли, но порядок между потоками не гарантируется.Пример: отладка пайплайна
tee raw.log < data.txt | grep error | tee filtered.log
Сохраняешь и исходные данные, и результат фильтрации.
Что это даёт: полный контроль над логами без потери интерактивности; удобно для CI, деплоя, отладки; прозрачная диагностика.
🔥 Ограничения и нюансы:
pipe меняет код возврата (решается pipefail или PIPESTATUS); pipefail не POSIX (bash/zsh/ksh); некоторые программы буферизуют вывод; при больших потоках — нагрузка на диск.🚪 Linux Ready | #практика