Как я могу перенаправить и добавить как stdout, так и stderr в файл с помощью Bash?

1182

Чтобы перенаправить stdout в усеченный файл в Bash, я знаю, что нужно использовать:

cmd > file.txt

Чтобы перенаправить stdout в Bash, добавив к файлу, я знаю, что нужно использовать:

cmd >> file.txt

Чтобы перенаправить оба stdout и stderr в усеченный файл, я знаю, что нужно использовать:

cmd &> file.txt

Как перенаправить оба файла stdout и stderr в файл? cmd &>> file.txt не работал у меня.

  • 29
    Я хотел бы отметить, что &> outfile - это специфичный для Bash (и других) код, а не переносимый. Путь к переносимости (аналогично добавлению ответов) всегда был и остается> outfile 2> & 1
Теги:
redirect
stream
pipe

6 ответов

1482
Лучший ответ
cmd >>file.txt 2>&1

Bash выполняет перенаправления слева направо следующим образом:

  • >>file.txt: Откройте file.txt в режиме добавления и переадресуйте stdout там.
  • 2>&1: Перенаправить stderr в "где stdout в настоящее время идет". В этом случае это файл, открытый в режиме добавления. Другими словами, &1 повторно использует дескриптор файла, который в настоящее время использует stdout.
  • 29
    работает отлично! но есть ли способ понять это или я должен рассматривать это как атомарную конструкцию bash?
  • 173
    Это простое перенаправление, операторы перенаправления оцениваются, как всегда, слева направо. >> файл: красный. STDOUT to file (режим добавления) (сокращение от 1 >> file) 2> & 1: Красный. STDERR в «куда идет stdout» Обратите внимание, что интерпретация «перенаправить STDERR в STDOUT» неверна.
Показать ещё 8 комментариев
284

Есть два способа сделать это, в зависимости от вашей версии Bash.

Классический и портативный (Bash pre-4) способ:

cmd >> outfile 2>&1

Непортируемый путь, начиная с Bash 4,

cmd &>> outfile

(аналог &> outfile)

Для хорошего стиля кодирования вы должны

  • решить, является ли переносимость проблемой (тогда используйте классический способ)
  • решить, является ли переносимость даже до Bash pre-4 проблемой (тогда используйте классический способ).
  • независимо от того, какой синтаксис вы используете, не изменяйте его в пределах того же script (путаница!)

Если ваш script уже начинается с #!/bin/sh (независимо от того, предназначено или нет), то решение Bash 4 и вообще любой Bash -специфический код не подходит.

Также помните, что Bash 4 &>> - это просто более короткий синтаксис - он не вводит никаких новых функций или чего-либо подобного.

Синтаксис (помимо другого синтаксиса перенаправления), описанный здесь: http://bash-hackers.org/wiki/doku.php/syntax/redirection#appending_redirected_output_and_error_output

  • 6
    Я предпочитаю & >>, так как это соответствует &> и >>. Также легче прочитать «добавить вывод и ошибки в этот файл», чем «отправить ошибки на вывод, добавить вывод в этот файл». Обратите внимание, что хотя Linux обычно имеет текущую версию bash, OS X, на момент написания, по-прежнему требует bash 4 для ручной установки через homebrew и т. Д.
  • 0
    Мне это нравится больше, потому что оно короче и содержит только два места в строке, так что, например, zsh сделает из "& >>"?
Показать ещё 2 комментария
79

В Bash вы также можете явно указать свои переадресации на разные файлы:

cmd >log.out 2>log_error.out

Добавление будет:

cmd >>log.out 2>>log_error.out
  • 6
    Перенаправление двух потоков в один и тот же файл с использованием вашей первой опции приведет к тому, что первый из них будет писать «поверх» второго, перезаписывая часть или все содержимое. Вместо этого используйте cmd >> log.out 2> log.out .
  • 3
    Спасибо, что поймали это; вы правы, один будет бить другого. Однако ваша команда тоже не работает. Я думаю, что единственный способ записать в тот же файл, как это было сделано до cmd >log.out 2>&1 . Я редактирую свой ответ, чтобы удалить первый пример.
59

В Bash 4 (а также ZSH 4.3.11):

cmd &>>outfile

просто из коробки

  • 1
    @AoeAoe: Это на самом деле работает и в Bash 4.
  • 2
    @all: это хороший ответ, так как он работает с bash и является кратким, поэтому я отредактировал, чтобы он явно упоминал bash.
Показать ещё 1 комментарий
31

Это должно работать нормально:

your_command 2>&1 | tee -a file.txt

Он сохранит все журналы в файле file.txt, а также сбросит их на терминал.

19

Попробуй это

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.

  • 0
    Ваш пример будет делать что-то отличное от запрошенного OP: он перенаправит stderr из You_command в stdout, а stdout из You_command в файл output.log . Кроме того, он не будет добавлен в файл, но перезапишет его.
  • 0
    Правильно: дескриптор файла может иметь любые значения, которые больше 3 для всех остальных файлов.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню