Как перенаправить вывод команды одновременно в файл и в stdout в bash
В bash, вызов foo отображает вывод этой команды на stdout.
Вызов foo > output перенаправляет вывод этой команды в указанный файл (в данном случае ‘output’).
Существует ли способ перенаправить вывод в файл и одновременно отображать его на stdout?
Для перенаправления вывода команд одновременно в файл и stdout в bash можно использовать команду tee. Наиболее распространенный подход - это передача вывода вашей команды в tee, которая затем будет записывать его как в терминал, так и в указанный файл. Например: command | tee filename перенаправляет stdout в оба места, а command 2>&1 | tee filename перенаправляет и stdout, и stderr в оба назначения.
Содержание
- Использование команды tee
- Перенаправление и stdout, и stderr
- Продвинутые техники
- Перенаправление на уровне скрипта
- Распространенные случаи использования
- Советы по устранению неполадок
Использование команды tee
Команда tee специально создана для этой цели. Она считывает данные со стандартного ввода и одновременно записывает их как в стандартный вывод, так и в один или несколько файлов.
Базовый синтаксис
command | tee filename
Пример:
ls -la | tee output.txt
Эта команда выведет содержимое каталога в терминал и одновременно запишет тот же вывод в файл output.txt.
Основные опции tee:
-aили--append: Добавлять содержимое в конец файла вместо перезаписи-iили--ignore-interrupts: Игнорировать прерывающие сигналы
Пример с добавлением в конец файла:
long_running_process | tee -a app.log
Перенаправление и stdout, и stderr
Чтобы перенаправить и стандартный вывод (stdout), и стандартный поток ошибок (stderr) одновременно в терминал и файл, необходимо сначала объединить дескрипторы файлов.
Метод 1: Сначала объединяем stderr с stdout
command 2>&1 | tee filename
Пример:
find . -name "*.txt" 2>&1 | tee search_results.txt
Метод 2: Использование сокращения |& (Bash 4+)
command |& tee filename
Пример:
curl -s https://example.com |& tee curl_output.log
Метод 3: Использование подстановки процесса для отдельной обработки
(command > >(tee stdout.log)) 2> >(tee stderr.log)
Продвинутые техники
Подстановка процесса для сложных сценариев
Подстановка процесса >(...) создает FIFO (именованный канал), который может быть прочитан одной командой и записан другой.
Пример: Раздельная обработка stdout и stderr в разные файлы с одновременным выводом обоих потоков в терминал
(echo 'ok'; echo 'error' >&2) 2> >(tee err.log) > >(tee out.log) | tee all.log
Запись в несколько файлов с помощью tee
Можно одновременно записывать в несколько файлов:
command | tee file1.txt file2.txt file3.txt
Условное перенаправление
Можно сделать перенаправление условным в зависимости от того, выводится ли информация в терминал:
if [ -t 1 ]; then
command | tee "$logfile"
else
command > "$logfile"
fi
Перенаправление на уровне скрипта
Для перенаправления вывода всего скрипта можно использовать exec:
Перенаправить весь вывод (stdout и stderr) для всего скрипта
#!/bin/bash
exec &> >(tee -a script.log)
echo "Это сообщение пойдет и в терминал, и в файл журнала"
some_command_with_errors
Условное перенаправление на уровне скрипта
#!/bin/bash
if [ -t 1 ]; then
exec &> >(tee -a "$logfile")
else
exec &> "$logfile"
fi
Распространенные случаи использования
Ведение журнала длительно работающих процессов
./long_running_script.sh | tee -a process.log
Разработка и отладка
make 2>&1 | tee build.log
Задачи системного администрирования
sudo apt update 2>&1 | tee apt_update.log
Мониторинг команд
tail -f /var/log/syslog | tee -a monitor.log
Обработка в конвейере (pipeline)
cat largefile.txt | grep "pattern" | tee filtered.txt | wc -l
Советы по устранению неполадок
Распространенные проблемы и решения
Проблема: Вывод stderr отсутствует
Решение: Убедитесь, что сначала перенаправляете stderr в stdout: command 2>&1 | tee file
Проблема: Ошибки прав доступа к файлу
Решение: Убедитесь, что у вас есть права на запись в целевой файл/каталог
Проблема: Вывод появляется с задержкой
Решение: Используйте tee -a вместо tee для избежания проблем с перезаписью
Проблема: Разное поведение в скриптах и интерактивной оболочке
Решение: Используйте set -o pipefail для правильной обработки ошибок в конвейерах
Вопросы производительности
- При очень большом объеме вывода рассмотрите возможность использования
tee -aдля избежания проблем с усечением файла - Несколько команд
teeмогут значительно повлиять на производительность - Для ведения журналов в продакшене рассмотрите возможность использования специализированных инструментов
Заключение
Ключевые выводы
- Команда
tee- это основной инструмент для перенаправления вывода одновременно в файл и stdout - Используйте
command 2>&1 | tee filenameдля захвата и stdout, и stderr - Подстановка процесса предлагает расширенные возможности для сложных сценариев перенаправления
execможет перенаправлять весь вывод на уровне скрипта- Понимание дескрипторов файлов (1=stdout, 2=stderr) необходимо для правильного перенаправления
Практические рекомендации
- Для простого ведения журнала: Используйте
command | tee filename - Для комплексного ведения журнала: Используйте
command 2>&1 | tee filename - Для скриптов: Рассмотрите возможность использования
exec &> >(tee -a logfile)для полного перенаправления - Всегда проверяйте права доступа к файлам перед перенаправлением вывода
- Используйте опцию
-aсtee, когда нужно добавлять содержимое в существующие файлы журнала
Связанные вопросы
- Как перенаправить только stderr одновременно в файл и терминал?
- Можно ли использовать tee с сжатым выводом (gzip)?
- В чем разница между
teeиtee -a? - Как обрабатывать цветовые коды при использовании tee с файлами журнала?
Для более сложных сценариев рассмотрите изучение подстановки процесса в bash и продвинутых техник манипуляции дескрипторами файлов.
Источники
- Stack Overflow - How to redirect output to a file and stdout
- Server Fault - Capturing STDERR and STDOUT to a file using ‘tee’
- Linux Bash - tee: Redirect output to files and stdout
- Baeldung on Linux - Redirect Output of a Process to a File and Standard Streams
- Unix & Linux Stack Exchange - Using exec and tee to redirect logs
- Super User - How to redirect output to both a file and stdout
- Reddit - Command tee file tee stderr and stdout issue
- Linux Hint - Redirecting stderr Using the tee Command