В bash вызов foo
будет отображать любой вывод из этой команды на stdout.
Вызов foo > output
будет перенаправлять любой вывод из этой команды в указанный файл (в этом случае "вывод" ).
Есть ли способ перенаправить вывод в файл и показать его на stdout?
Требуемая команда называется 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
$ 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
Другой способ, который работает для меня, -
<command> |& tee <outputFile>
как показано в gnu bash manual
Пример:
ls |& tee files.txt
Если '| &, command1s стандартная ошибка, в дополнение к ее стандартным выводам, подключается к стандартным входам command2s через трубу; это сокращение для 2 > & 1 |. Это неявное перенаправление стандартной ошибки на стандартный вывод выполняется после любых переназначений, указанных в команде.
Для получения дополнительной информации см. redirection
$?
после этого он вернет код состояния tee
, что, вероятно, не то, что вы хотите. Вместо этого вы можете использовать ${PIPESTATUS[0]}
.
tee
- ваш друг.
whatever | tee logfile.txt
используя tail -f output
, должен работать.
Бонусный ответ, так как этот прецедент привел меня сюда:
В случае, если вам нужно сделать это как другой пользователь
echo "some output" | sudo -u some_user tee /some/path/some_file
Обратите внимание, что эхо произойдет, когда вы и запись файла произойдет как "some_user", что будет работать NOT, если вы должны запустить echo как "some_user" и перенаправить вывод с помощью → "some_file", потому что перенаправление файлов произойдет как вы.
Подсказка: tee также поддерживает добавление с флагом -a, если вам нужно заменить строку в файле в качестве другого пользователя, который вы могли бы выполнить sed в качестве желаемого пользователя.
tee идеально подходит для этого, но это также сделает работу
ls -lr / > output | cat output
;
, вывод будет сильно задерживаться во время медленной команды.