Перенаправление и tee: сохраняем вывод без потери диагностики

Перенаправление меняет, откуда процесс читает и куда пишет, ещё до его запуска. Оно позволяет сохранить отчёт, отделить диагностику, подать файл как stdin или одновременно видеть…

Перенаправление меняет, откуда процесс читает и куда пишет, ещё до его запуска. Оно позволяет сохранить отчёт, отделить диагностику, подать файл как stdin или одновременно видеть поток на экране и записывать его через tee.

Операторы чтения и записи

<input подключает файл к stdin, >output создаёт или обнуляет файл для stdout, а >>output добавляет данные в конец. Номер перед оператором выбирает дескриптор: 2>errors.log относится к stderr.

wc -l </etc/services
printf '%s\n' first >events.log
printf '%s\n' second >>events.log
ls /missing >listing.txt 2>listing.err

Обнуление через > происходит до выполнения команды. Ошибка в аргументах не вернёт старое содержимое файла. Для важного отчёта безопаснее писать во временный файл и заменять целевой только после успешной проверки.

Почему порядок 2>&1 имеет значение

2>&1 означает «направить stderr туда, куда stdout направлен сейчас». Поэтому следующие команды неэквивалентны:

command >combined.log 2>&1
command 2>&1 >stdout-only.log

В первой строке stdout сначала указывает на файл, затем stderr копирует это назначение. Во второй stderr сначала копирует терминал, и лишь после этого stdout переключается на файл. Bash обрабатывает перенаправления слева направо.

Наблюдение через tee

tee читает stdin, пишет копию в файл и продолжает поток через stdout. Это полезно в CI или при долгой диагностике.

set -o pipefail
run-checks 2>&1 | tee checks.log
status=$?
printf 'checks status=%s\n' "$status"

Без pipefail status относится к tee, и падение run-checks может быть скрыто. Для добавления вместо перезаписи используется tee -a, но бесконтрольный append постепенно заполняет диск.

Ошибка и диагностика

Распространённый дефект — sudo command >protected/file: перенаправление выполняет текущий shell до запуска sudo, поэтому запись получает права обычного пользователя и падает. Проверьте владельца каталога и границу процесса. Если операция действительно разрешена, данные можно передать привилегированному tee: printf '%s\n' value | sudo tee /protected/file >/dev/null. Не превращайте этот приём в способ обходить осмысленные права.

Практика

Напишите команду, которая выдаёт stdout, stderr и status 9. Сохраните каналы отдельно, затем вместе, каждый раз проверьте содержимое и status. После этого пропустите общий поток через tee с pipefail. Объясните, почему экран и файл совпадают, а код завершения не обязан принадлежать tee.

Что важно запомнить

Источники