it-swarm.com.ru

Как перенаправить вывод в файл и стандартный вывод

В bash вызов foo будет отображать любой вывод этой команды на стандартный вывод.

Вызов foo > output перенаправит любой вывод этой команды в указанный файл (в данном случае "output").

Есть ли способ перенаправить вывод в файл и он отображается на стандартный вывод?

813
SCdF

Желаемая команда называется tee:

foo | tee output.file

Например, если вы заботитесь только о stdout:

ls -a | tee output.file

Если вы хотите включить stderr, выполните:

program [arguments...] 2>&1 | tee outfile

2>&1 перенаправляет канал 2 (стандартный вывод/стандартная ошибка) в канал 1 (стандартный вывод/стандартный вывод), так что оба записываются как стандартный вывод. Он также направляется в указанный выходной файл с помощью команды tee.

Кроме того, если вы хотите добавить в файл журнала, используйте tee -a как:

program [arguments...] 2>&1 | tee -a outfile
1112
Zoredache
$ program [arguments...] 2>&1 | tee outfile

2>&1 выводит потоки stderr и stdout. tee outfile принимает поток, который получает, и записывает его на экран и в файл "outfile".

Это, вероятно, то, что ищет большинство людей. Скорее всего, какая-то программа или скрипт долго работают и выдают много результата. Пользователь хочет периодически проверять его на предмет прогресса, но также хочет, чтобы вывод был записан в файл.

Проблема (особенно при смешивании потоков stdout и stderr) состоит в том, что существует зависимость от потоков, сбрасываемых программой. Например, если все записи в stdout не сброшены, но все записи в stderr are сброшены, то в результате они будут выходить из хронологического порядка файл и на экране.

Также плохо, если программа выдает только 1 или 2 строки каждые несколько минут, чтобы сообщить о прогрессе. В таком случае, если вывод не был сброшен программой, пользователь даже часами не будет видеть никакого вывода на экране, потому что ни один из них не будет проталкиваться через канал в течение нескольких часов.

Обновление: программа unbuffer, входящая в состав пакета expect, решит проблему буферизации. Это заставит stdout и stderr немедленно записать на экран и в файл и синхронизировать их при объединении и перенаправлении на tee. Например.:

$ unbuffer program [arguments...] 2>&1 | tee outfile
469
Matthew Alpert

Другой способ, который работает для меня, это

<command> |& tee  <outputFile>

как показано в руководство по gnu bash

Пример:

ls |& tee files.txt

Если используется '| &', стандартная ошибка command1 , в дополнение к стандартный вывод , подключается к стандартному вводу command2 через канал; это сокращение для 2> & 1 |. Это неявное перенаправление стандартной ошибки на стандартный вывод выполняется после любого перенаправления, указанного командой.

Для получения дополнительной информации обратитесь перенаправление

111
tsenapathy

Вы можете в первую очередь использовать Zoredacheрешение , но если вы не хотите перезаписывать выходной файл, вы должны написать tee с опцией -a следующим образом:

ls -lR / | tee -a output.file
16
O.Badr

Что-то добавить ...

Unbuffer пакета имеет проблемы с поддержкой некоторых пакетов в Fedora и Redhat Unix.

Откладывая в сторону неприятности

Следующее сработало для меня

bash myscript.sh 2>&1 | tee output.log

Спасибо ScDF & Мэтью ваш вклад сэкономил мне много времени ..

11
nitinr708

использование tail -f output должно работать.

6
Chuck Phillips

Бонусный ответ, так как этот вариант использования привел меня сюда:

В случае, если вам нужно сделать это как какой-то другой пользователь

echo "some output" | Sudo -u some_user tee /some/path/some_file

Обратите внимание, что эхо произойдет, когда вы и запись в файл произойдут как "some_user", что будет НЕ работать, если вы должны запустить эхо как "some_user" и перенаправить вывод с помощью >> "some_file", потому что перенаправление файлов будет происходить как вы.

Подсказка: tee также поддерживает добавление с флагом -a, если вам нужно заменить строку в файле другим пользователем, вы можете выполнить sed в качестве нужного пользователя.

3
jorfus

< command > |& tee filename # это создаст файл "имя файла" со статусом команды в качестве контента. Если файл уже существует, он удалит существующий контент и запишет статус команды.

< command > | tee >> filename # это добавит статус к файлу, но не напечатает статус команды на standard_output (screen).

Я хочу напечатать что-нибудь с помощью "эхо" на экране и добавить эти данные в файл

echo "hi there, Have to print this on screen and append to a file" 
1
kiran sai

Вы можете сделать это для всего сценария, используя что-то подобное в начале сценария:

#!/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

Это перенаправляет выходные данные как stderr, так и stdout в файл с именем mylogfileи и все идет на stdout одновременно.

Используются некоторые глупые трюки:

  • используйте exec без команды для установки перенаправлений,
  • используйте tee для дублирования выходных данных,
  • перезапустите скрипт с нужными перенаправлениями,
  • используйте специальный первый параметр (простой символ NUL, указанный в специальной записи bash $'string'), чтобы указать, что сценарий перезапускается (в исходной работе эквивалентный параметр не может использоваться),
  • попытайтесь сохранить исходное состояние завершения при перезапуске сценария с помощью параметра pipefail.

Некрасиво, но полезно для меня в определенных ситуациях.

0
Bruno BEAUFILS