Как я могу перенаправить и добавить как 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 выполняет перенаправления слева направо следующим образом:

  1. >>file.txt: Открыто file.txt в режиме добавления и перенаправления stdout там.
  2. 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Но такой подход мне кажется более естественным и понятным:

  1. Перенаправить stderr на стандартный вывод.
  2. Перенаправить новый стандартный вывод, добавив в файл.

Кроме того, скобки убирают любую двусмысленность порядка, особенно если вы хотите вместо этого направить 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, так и stderr

exec >> file exec 2>&1 Как упомянул Джонатан Леффлер в своем комментарии:

у руководителя две отдельные работы. Первый — заменить выполняющуюся в данный момент оболочку (скрипт) новой программой. Другой — изменение перенаправления ввода-вывода в текущей оболочке. Это отличается отсутствием аргументов для exec.

Другие вопросы по тегам