Как я могу использовать магию BASH для достижения этой цели?
Я хочу видеть только вывод stderr на экране,
но я хочу, чтобы и stdout, и stderr были записаны в файл.
Уточнение: я хочу, чтобы и stdout, и stderr оказались в одном файле. По порядку они случаются.
К сожалению, ни один из ответов ниже не делает этого.
bash
shell
io-redirection
Andreas
источник
источник
Ответы:
Даже без какого-либо перенаправления или только с чем
>logfile 2>&1
, вы не гарантированно увидите выходные данные в порядке генерации.Для начала stdout из приложения будет буферизован строкой (в tty) или буферизован (в конвейер), но stderr не буферизован, поэтому отношения между порядком вывода нарушены, насколько это касается читателя. Последующие этапы в любом конвейере, который вы могли бы придумать, не получат детерминированно упорядоченный доступ к двум потокам (концептуально они происходят параллельно, и вы всегда подчиняетесь планировщику - если к тому времени, когда ваш читатель получит фрагмент, автор уже записано в обе трубы, вы не можете сказать, что было первым).
«[T] он приказывает им случиться» только действительно известно приложению. Упорядочение вывода через stdout / stderr - хорошо известная, возможно, классическая проблема.
источник
Когда вы используете конструкцию:
1>stdout.log 2>&1
и stderr, и stdout перенаправляются в файл, потому что перенаправление stdout настроено до перенаправления stderr .Если вы измените порядок, вы можете перенаправить stdout в файл, а затем скопировать stderr в stdout, чтобы вы могли передать его
tee
.источник
tee -a
и тот же файл, чтобы использовать1>
для суммирования обоих выходных данных в одном файле. Что-то вроде:./test 2>&1 1>out+err.log | tee -a out+err.log
wget -O - www.google.de
для меня. (сравните с решением ниже)tee -a
не будет работать надежно, чтобы иметь тот же вывод, который был бы на консоли, если бы ничего не было перенаправлено. Вывод, который проходит через,tee
может быть немного задержан по сравнению с выводом, полученным непосредственно из команды, и поэтому может появиться позже в журнале.Я смог сделать это, поместив следующую строку в верхней части сценария bash:
Это перенаправит stdout в file
log
(1>>log
), затем переместит stderr в filelog
(2> >(tee -a log
) и перенаправит его обратно в stderr (>&2)
. Таким образом, я получаю один файлlog
, который показывает и stdout, и stderr по порядку, и stderr также отображается на экране как обычно.Подвох в том, что он работает только при добавлении файла. Если я не добавляю, кажется, что два перенаправления перекрывают друг друга, и я получаю только один из последних выходов.
источник
Вы хотите продублировать поток ошибок, чтобы он появлялся как на консоли, так и в файле журнала. Инструмент для этого есть
tee
, и все, что вам нужно сделать, это применить его к потоку ошибок. К сожалению, нет стандартной конструкции оболочки для передачи потока ошибок команды в другую команду, поэтому требуется небольшая перестановка дескриптора файла.источник
tee
здесь тоже вводится задержка. Я не думаю, что есть чистое решение для оболочки. На самом деле мне интересно, есть ли решение, не модифицируя приложение каким-либо образом.Чтобы записать stderr на экран и записать ОБА stderr и stdout в файл - И получить строки для stderr и stdout в той же последовательности, в которой они были бы, если бы оба были записаны на экран:
Оказывается, это сложная проблема, особенно та часть, которая касается «той же последовательности», которую можно ожидать, если вы просто напишите их на экран. Проще говоря: запишите каждый в свой файл, сделайте некоторую магию фонового процесса, чтобы пометить каждую строку (в каждом файле) точным временем, когда была произведена строка, а затем: «tail --follow» файл stderr на экран , но чтобы увидеть оба «stderr» и «stdout» вместе - по порядку - отсортируйте два файла (с отметками точного времени на каждой строке) вместе.
Код:
Да, это кажется сложным, и это приводит к 4 выходным файлам (2 из которых вы можете удалить). Похоже, что эту проблему трудно решить, поэтому потребовалось несколько механизмов.
В конце, чтобы увидеть результаты ОБА stdout и stderr в последовательности, которую вы ожидаете, запустите это:
Единственная причина, по которой последовательность, по крайней мере, очень близка к тому, что было бы, если бы stdout и stderr просто были выведены на экран, заключается в следующем: каждая строка помечена меткой времени до миллисекунды.
Чтобы увидеть stderr на экране во время процесса, используйте это:
Надеюсь, что это поможет кому-то, кто прибыл сюда намного позже, чем был задан первоначальный вопрос.
источник
Позвольте
f
быть команда, которую вы хотели бы выполнить, то этодолжен дать вам то, что вы хотите. Например,
wget -O - www.google.de
будет выглядеть так:источник
Учитывая то, что я прочитал здесь, единственное решение, которое я вижу, - это добавлять каждую строку, STOUT или STERR, к временному интервалу / метке времени. date +% s будет в секундах, но это будет медленно, чтобы поддерживать порядок. Также журнал должен был бы быть как-то отсортирован. Больше работы, чем я способен.
источник
Я боролся с этим точным требованием, и в конце концов не смог найти простое решение. Вместо этого я закончил тем, что сделал следующее:
Он добавляет stdout и stderr в правильном порядке чередования в файл журнала. И если какие-либо ошибки произошли (как определено состоянием выхода команды), он отправляет весь вывод (stdout и stderr) в stdout, снова в правильном порядке чередования. Я нашел это разумным компромиссом для моих нужд. Если вам нужен файл журнала с однократным запуском, а не растущий многопоточный, это еще проще:
источник
stderr для замены команд
tee -a
и добавление stdout в тот же файл:и обратите внимание: также убедитесь, что в правильном порядке (но без stderr-show) есть команда 'unbuffer' из инструментов 'wait', которая имитирует tty и сохраняет порядок stdout / err, как это будет показано на терминале:
источник