Как перенаправить вывод в файл и stdout
В bash вызов foo
будет отображать любой вывод из этой команды на stdout.
Вызов foo > output
будет перенаправлять любой вывод из этой команды в указанный файл (в этом случае "вывод" ).
Есть ли способ перенаправить вывод в файл и показать его на stdout?
Ответы
Ответ 1
Требуемая команда называется tee
:
foo | tee output.file
Например, если вы только заботитесь о stdout:
ls -a | tee output.file
Если вы хотите включить stderr, выполните:
program [arguments...] 2>&1 | tee outfile
2>&1
перенаправляет канал 2 (stderr/стандартная ошибка) в канал 1 (стандартный вывод/стандартный вывод), так что оба они записываются как stdout. Он также направляется к данному выходному файлу с командой tee
.
Кроме того, если вы хотите добавить в файл журнала, используйте tee -a
как:
program [arguments...] 2>&1 | tee -a outfile
Ответ 2
$ program [arguments...] 2>&1 | tee outfile
2>&1
сбрасывает потоки stderr и stdout.
tee outfile
берет поток, который он получает, и записывает его на экран и в файл "outfile".
Это, вероятно, то, что большинство людей ищет. Вероятная ситуация - это какая-то программа, или script долго работает и производит много выходных данных. Пользователь хочет периодически проверять его на наличие прогресса, но также хочет, чтобы результат был записан в файл.
Проблема (особенно при смешивании потоков stdout и stderr) заключается в том, что существует зависимость от потоков, которые сбрасываются программой. Если, например, все записи в stdout не сбрасываются, но все записи в stderr очищаются, то они будут в конечном итоге отставать от хронологического порядка в выходном файле и на экране.
Это также плохо, если программа выводит только 1 или 2 строки каждые несколько минут, чтобы сообщить о прогрессе. В таком случае, если выход не был сброшен программой, пользователь не будет даже видеть какой-либо вывод на экране в течение нескольких часов, потому что ни один из них не будет проталкиваться через трубу в течение нескольких часов.
Обновление. Программа unbuffer
, входящая в пакет expect
, решит проблему буферизации. Это заставит stdout и stderr немедленно записывать на экран и файл и синхронизировать их при объединении и перенаправлении на tee
. Например:.
$ unbuffer program [arguments...] 2>&1 | tee outfile
Ответ 3
Другой способ, который работает для меня, -
<command> |& tee <outputFile>
как показано в gnu bash manual
Пример:
ls |& tee files.txt
Если '| &, command1s стандартная ошибка, в дополнение к ее стандартным выводам, подключается к стандартным входам command2s через трубу; это сокращение для 2 > & 1 |. Это неявное перенаправление стандартной ошибки на стандартный вывод выполняется после любых переназначений, указанных в команде.
Для получения дополнительной информации см. redirection
Ответ 4
tee
- ваш друг.
whatever | tee logfile.txt
Ответ 5
В основном вы можете использовать Zoredache решение, но если вы не хотите перезаписывать выходной файл, вы должны написать tee с параметром -a следующим образом:
ls -lR / | tee -a output.file
Ответ 6
Что-то добавить...
В пакете unbuffer есть проблемы с поддержкой некоторых пакетов в версиях fedora и redhat unix.
Отказ от проблем
После работы для меня
bash myscript.sh 2>&1 | tee output.log
Спасибо ScDF и matthew ваши входы сэкономили мне много времени..
Ответ 7
используя tail -f output
, должен работать.
Ответ 8
Бонусный ответ, так как этот прецедент привел меня сюда:
В случае, если вам нужно сделать это как другой пользователь
echo "some output" | sudo -u some_user tee /some/path/some_file
Обратите внимание, что эхо произойдет, когда вы и запись файла произойдет как "some_user", что будет работать NOT, если вы должны запустить echo как "some_user" и перенаправить вывод с помощью → "some_file", потому что перенаправление файлов произойдет как вы.
Подсказка: tee также поддерживает добавление с флагом -a, если вам нужно заменить строку в файле в качестве другого пользователя, который вы могли бы выполнить sed в качестве желаемого пользователя.
Ответ 9
< command > |& tee filename
# это создаст файл "filename" со статусом команды в качестве контента. Если файл уже существует, он удалит существующий контент и запишет статус команды.
< command > | tee >> filename
< command > | tee >> filename
# это добавит статус к файлу, но не выведет статус команды на standard_output (screen).
Я хочу напечатать что-нибудь с помощью "эхо" на экране и добавить эти данные в файл
echo "hi there, Have to print this on screen and append to a file"
Ответ 10
Вы можете сделать это для всего сценария, используя что-то подобное в начале сценария:
#!/usr/bin/env bash
test x$1 = x$'\x00' && shift || { set -o pipefail ; ( exec 2>&1 ; $0 $'\x00' "[email protected]" ) | tee mylogfile ; exit $? ; }
# do whaetever you want
Это перенаправлять как потоки вывода выводит в файл с именем mylogfile
и пусть все идет на стандартный вывод одновременно.
Используются некоторые глупые трюки:
- использовать
exec
без команды для настройки перенаправлений, - используйте
tee
для дублирования выходов, - перезапустите скрипт с нужными перенаправлениями,
- используйте специальные первые параметры (простой
NUL
указанный в специальной нотации $'string'
bash), чтобы указать, что сценарий перезапускается (в вашей исходной работе эквивалентный параметр не может использоваться), - попытайтесь сохранить исходное состояние завершения при перезапуске сценария с помощью параметра
pipefail
.
Некрасиво, но полезно для меня в определенных ситуациях.
Ответ 11
tee идеально подходит для этого, но это также сделает работу
ls -lr / > output | cat output