Добавлять текст в перенаправления stderr в bash - PullRequest
12 голосов
/ 07 января 2009

Сейчас я использую exec для перенаправления stderr в журнал ошибок с

exec 2>> ${errorLog}

Единственным недостатком является то, что мне нужно начинать каждый запуск с отметки времени, так как exec просто помещает текст прямо в файл журнала. Есть ли способ перенаправить stderr, но я могу добавить к нему текст, например, отметку времени?

Ответы [ 5 ]

16 голосов
/ 07 января 2009

Это очень интересно. Я спросил парня, который хорошо знает bash, и он сказал мне так:

 foo() { while IFS='' read -r line; do echo "$(date) $line" >> file.txt; done; };

Во-первых, это создает функцию, читающую одну строку необработанного ввода из stdin, в то время как присвоение IFS заставляет его не игнорировать пробелы. Прочитав одну строку, он выводит ее с соответствующими данными. Затем вы должны указать bash перенаправить stderr в эту функцию:

exec 2> >(foo)

Все, что вы пишете в stderr, теперь будет проходить через функцию foo. Обратите внимание, что когда вы делаете это в интерактивной оболочке, вы больше не увидите подсказку, потому что она печатается в stderr, а чтение в foo буферизуется строкой:)

1 голос
/ 08 августа 2011

Вы можете просто использовать:

exec 1> >( sed "s/^/$(date '+[%F %T]'): /" | tee -a ${LOGFILE}) 2>&1

Это не полностью решит вашу проблему с приглашением, которое не отображается (оно будет отображаться через короткое время, но не в реальном времени, так как канал будет кэшировать некоторые данные ...), но будет отображать вывод 1: 1 на stdout как ну как в файле.

Единственная проблема, которую я не мог решить, это сделать это из функции, поскольку она открывает подоболочку, где exec бесполезен для основной программы ...

0 голосов
/ 28 октября 2014

В этом примере перенаправляются stdout и stderr без потери оригинальных stdout и stderr. Также ошибки в обработчике stdout записываются в обработчик stderr. Файловые дескрипторы сохраняются в переменных и закрываются в дочерних процессах. Баш заботится о том, чтобы не произошло столкновений.

#! /bin/bash

stamp ()
{
  local LINE
  while IFS='' read -r LINE; do
    echo "$(date '+%Y-%m-%d %H:%M:%S,%N %z') $$ $LINE"
  done
}

exec {STDOUT}>&1
exec {STDERR}>&2
exec 2> >(exec {STDOUT}>&-; exec {STDERR}>&-; exec &>> stderr.log; stamp)
exec > >(exec {STDOUT}>&-; exec {STDERR}>&-; exec >> stdout.log; stamp)

for n in $(seq 3); do
  echo loop $n >&$STDOUT
  echo o$n
  echo e$n >&2
done

Для этого требуется текущая версия Bash, но благодаря Shellshock в настоящее время можно положиться на это.

0 голосов
/ 17 марта 2014
cat q23123  2> tmp_file ;cat tmp_file | sed -e "s/^/$(date '+[%F %T]'): /g" >> output.log; rm -f tmp_file 
0 голосов
/ 26 июня 2009

Я просто искал такую ​​же аккуратную вещь. После просмотра этого поста я увидел еще один многообещающий подход: http://utcc.utoronto.ca/~cks/space/blog/unix/PipingJustStderr

...