Передать стандартную ошибку в файл и оставить ее при стандартной ошибке?


2

У меня есть скрипт (фрагмент), для которого я регистрирую вывод и стандартную ошибку:

#!/bin/sh
#...
{
   date "+%Y-%m-%d %T"
   cd $workdir
   ls -ltr validfile badfile #example command that provides stdout, stderr
} | tee -a $logfile

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

#!/bin/sh
#...
{
   date "+%Y-%m-%d %T"
   cd $workdir
   ls -ltr validfile badfile
} 2>&1 | tee -a $logfile

Но эта версия в скрипте при вызове из командной строки не позволит мне разобрать ошибки:

$ ./script.sh 2>/dev/null

Просто покажет все стандартные и стандартные ошибки. Что если на этот раз я хочу просто поглотить ошибки?

Можете ли вы показать мне, как передать стандартную ошибку в журнал, но оставить ее при стандартной ошибке, когда она вызывается через командную строку или другой скрипт?

AIX 7.1, ksh (без bash)

Ответы:


3

Используя некоторую причудливую переадресацию вывода, можно добиться этого без базового перенаправления bash на процессы.

Регистрация стандартной ошибки и ее сохранение в канале стандартных ошибок

#!/bin/sh
exec 4>&1    # important as it "saves" stdout (usually /dev/tty2 for example)
exec 3>&1    # work-in-progress file descriptor
logfile=/var/log/myscript.out

{
   {
      date "+%Y-%m-%d %T"
      cd $workdir
      ls -ltr validfile badfile
   } 2>&1 1>&3 | tee -a $logfile 1>&2 2>/dev/null 3>&4
} 3>&1 | tee -a $logfile

exec 4>&-   # proper form is to clean up when you're done
exec 3>&-

Пояснение:
exec 4>&1и exec 3>&1создайте новые файловые дескрипторы 3 и 4, которые оба указывают на то, на что указывает стандарт (ваш терминал, скорее всего).

2>&1перенаправляет стандартную ошибку всей фигурной скобки второго уровня в стандартный вывод. 1>&3перенаправляет стандартный поток на то, на что указывает fd3 (который является стандартным, но не на канал 1, что важно!)

| tee -a $logfileдублирует стандартное входящее (исходя из фигурных скобок второго уровня, то есть старого stderr) как в лог-файл, так и в стандартный выход. 1>&2перемещает стандарт на стандартную ошибку (поэтому обратно туда, где она принадлежит) . 2>/dev/nullВероятно, это не нужно, но он перенаправляет любую ошибку, выводимую из тройника, и удаляет ее. 3>&4перенаправляет канал 3 на канал 4 (который, кстати, указывает на стандартный вывод, помните?).

3>&1берет трубу 3 из фигурных скобок первого уровня и отправляет ее в обычный стандарт . | tee -a $logfileзахватывает стандартный ввод (который является [откорректированным] стандартом из фигурных скобок) и дублирует его в журнал и в стандартный вывод.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.