Как я могу перенаправить и добавить как stdout, так и stderr в файл с помощью Bash?
Чтобы перенаправить стандартный вывод в усеченный файл в Bash, я знаю использовать:
cmd > file.txt
Чтобы перенаправить стандартный вывод в Bash, добавив в файл, я знаю использовать:
cmd >> file.txt
Чтобы перенаправить как stdout, так и stderr в усеченный файл, я знаю использовать:
cmd &> file.txt
Как перенаправить как stdout, так и stderr при добавлении в файл? cmd &>> file.txt
не работал для меня.
10 ответов
cmd >>file.txt 2>&1
Bash выполняет перенаправления слева направо следующим образом:
>>file.txt
: Открытоfile.txt
в режиме добавления и перенаправленияstdout
там.2>&1
: Перенаправлениеstderr
кудаstdout
В настоящее время это файл, открытый в режиме добавления. Другими словами,&1
повторно использует дескриптор файла, которыйstdout
в настоящее время использует.
Есть два способа сделать это, в зависимости от вашей версии Bash.
Классический и портативный (Bash pre-4) способ это:
cmd >> outfile 2>&1
Непортативный способ, начиная с Bash 4:
cmd &>> outfile
(аналог &> outfile
)
Для хорошего стиля кодирования, вы должны
- решить, является ли переносимость проблемой (тогда используйте классический способ)
- решить, является ли переносимость даже в Bash pre-4 проблемой (тогда используйте классический способ)
- независимо от того, какой синтаксис вы используете, не меняйте его в одном и том же сценарии (путаница!)
Если ваш скрипт уже начинается с #!/bin/sh
(независимо от того, предназначен ли он или нет), тогда решение Bash 4 и вообще любой специфичный для Bash код не годятся.
Также помните, что Bash 4 &>>
это просто более короткий синтаксис - он не вводит никакой новой функциональности или чего-то в этом роде.
Синтаксис (помимо другого синтаксиса перенаправления) описан здесь: http://bash-hackers.org/wiki/doku.php/syntax/redirection
В Bash вы также можете явно указать ваши перенаправления в разные файлы:
cmd >log.out 2>log_error.out
Добавление будет:
cmd >>log.out 2>>log_error.out
Это должно работать нормально:
your_command 2>&1 | tee -a file.txt
Он будет хранить все журналы в файле file.txt, а также выводить их на терминал.
В Bash 4 (а также в ZSH 4.3.11):
cmd &>>outfile
просто из коробки
Попробуй это
You_command 1>output.log 2>&1
Ваше использование &>x.file работает в bash4. простите за это: (
Вот несколько дополнительных советов.
0, 1, 2... 9 - файловые дескрипторы в bash.
0 обозначает stdin
, 1 обозначает stdout
, 2 обозначает stderror
, 3~9 является запасным для любого другого временного использования.
Любой дескриптор файла может быть перенаправлен на другой дескриптор файла или файл с помощью оператора >
или же >>
(Добавить).
Использование: < file_descriptor>> < filename | & file_descriptor>
Пожалуйста, обратитесь к http://www.tldp.org/LDP/abs/html/io-redirection.html
Перенаправления из внутреннего скрипта
Вы можете планировать перенаправления из самого скрипта
#!/bin/bash
exec 1>>logfile.txt
exec 2>&1
/bin/ls -ld /tmp /tnt
Запуск этого создаст / добавит
logfile.txt
, содержащий:
/bin/ls: cannot access '/tnt': No such file or directory
drwxrwxrwt 2 root root 4096 Apr 5 11:20 /tmp
Вход в множество разных файлов
Вы можете создать два разных файла журнала, добавив к одному общему журналу и воссоздав еще один последний журнал:
#!/bin/bash
if [ -e last.log ] ;then
mv -f last.log last.old
fi
exec 1> >(tee -a overall.log /dev/tty >last.log)
exec 2>&1
ls -ld /tnt /tmp
Запуск этого сценария приведет к
- если они уже существуют, переименуйте их в (перезапись
last.old
если они есть). - создать новый .
- добавить все к
- выводить все на терминал.
Простые И комбинированные бревна
#!/bin/bash
[ -e last.err ] && mv -f last.err lasterr.old
[ -e last.log ] && mv -f last.log lastlog.old
exec 2> >(tee -a overall.err combined.log /dev/tty >last.err)
exec 1> >(tee -a overall.log combined.log /dev/tty >last.log)
ls -ld /tnt /tmp
Так что у тебя есть
-
last.log
файл журнала последнего запуска -
last.err
файл ошибок последнего запуска -
lastlog.old
предыдущий файл журнала запуска -
lasterr.old
предыдущий файл ошибок запуска -
overall.log
добавлен общий файл журнала -
overall.err
добавлен файл общей ошибки -
combined.log
добавлен объединенный файл общей ошибки и журнала. - все еще выводится на терминал
Я удивлен, что за почти десять лет никто еще не опубликовал этот подход:
Если вы используете старые версии Bash где &>>
недоступен, вы также можете сделать:
(cmd 2>&1) >> file.txt
Это порождает подоболочку, поэтому она менее эффективна, чем традиционный подход cmd >> file.txt 2>&1
Но такой подход мне кажется более естественным и понятным:
- Перенаправить stderr на стандартный вывод.
- Перенаправить новый стандартный вывод, добавив в файл.
Кроме того, скобки убирают любую двусмысленность порядка, особенно если вы хотите вместо этого направить stdout и stderr в другую команду.
Если вас волнует порядок содержимого двух потоков, см. ответ @ed-morton на аналогичный вопрос здесь .
Это ужасно хорошо!
Перенаправьте вывод в файл журнала и стандартный вывод в текущем скрипте.
Обратитесь к /questions/20459075/kak-perenapravit-vyivod-vsego-stsenariya-obolochki-vnutri-samogo-stsenariya/20459088#20459088, очень просто и понятно, он перенаправляет весь вывод сценария в файл журнала и стандартный вывод, включая сценарии, вызываемые в сценарии:
exec > >(tee -a "logs/logdata.log") 2>&1 печатает журналы на экране, а также записывает их в файл shriyog 2 февраля 2017, в 9:20
Обычно мы размещаем один из них в верхней части сценария или рядом с ним. Скрипты, которые анализируют свои командные строки, выполняют перенаправление после анализа.
Отправить стандартный вывод в файл
exec > файл со stderr
exec > file
exec 2>&1 добавить в файл как stdout, так и stderrexec >> file exec 2>&1 Как упомянул Джонатан Леффлер в своем комментарии:
у руководителя две отдельные работы. Первый — заменить выполняющуюся в данный момент оболочку (скрипт) новой программой. Другой — изменение перенаправления ввода-вывода в текущей оболочке. Это отличается отсутствием аргументов для exec.