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

671
bgStack15

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

#!/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)

2

1 ответ на вопрос

3
bgStack15

Using some fancy output redirection, it is possible to achieve this without your basic bash redirection-to-processes.

Logging standard error and keeping it on the standard error pipe

#!/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>&- 

Explanation:
exec 4>&1 and exec 3>&1 make new file descriptors 3 and 4, which both point to whatever standard out is pointing to (your terminal, most likely).

2>&1 redirects standard error of the whole second-level curly brace to standard out. 1>&3 redirects standard out to whatever fd3 is pointing to (which is standard out, but just not in pipe 1, which is significant!)

| tee -a $logfile duplicates standard in (coming from the second-level curly braces, so the old stderr) to both the logfile and also standard out. 1>&2 moves standard out to standard error (so back where it belongs). 2>/dev/null probably isn't necessary, but it redirects any error output from tee and trashes it. 3>&4 redirects pipe 3 to pipe 4 (which incidentally is pointing to stdout, remember?).

3>&1 takes pipe 3 of the first-level braces and sends it to regular standard out. | tee -a $logfile captures standard input (which is the [adjusted] standard out of the braces) and duplicates it to the log and to standard out.

Похожие вопросы