Как перенаправить вывод в файл и 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