SDERR和STDOUT用于logging的BASH脚本中的文件描述符

我正在尝试将基本日志logging添加到脚本,每天将由cron作业运行。 基本上它沿着这些线路:

LOGFILE=mylog.txt exec 3<>$LOGFILE 2>&1 commands ... exec 3>&- 

基本上所有我需要知道的是如何正确写入第三行,以便STDERR和STDOUT都被写入FD 3,这是日志文件。 我一直在摸索它,可悲的是TLDP的解释并不是最好的 – 大多数关于redirect和文件描述符的教程都没有涉及到这种深度。 任何帮助真的不胜感激。

exec >&3 2>&3

和SF要求我input更多的字符,但这就是它的一切。

我正在使用这个简单的日志logging:

 exec > >(tee -a $LOGFILE) exec 2> >(tee -a >(sed 's/^/STDERR: /' >>$LOGFILE) 1>&2) 

对于复杂的东西,我有一个函数在log-function.sh:

 log() { #{{{ local DAYS_TO_KEEP_THE_LOG=30 local LOG_DATE_FORMAT="+%Y-%m-%d %H:%M:%S" local FILESUFIX_DATE_FORMAT="+%Y-%m-%d_%H%M%S" case $1 in --disable-output-redirection) OUTPUT_NOT_LOGGED=1 log Output redirection is disabled. Only explicit \"log\" calls will be logged. return ;; --enable-timestamps) if [[ $OUTPUT_NOT_LOGGED == 1 ]];then log The option --enable-timestamps is ignored if --disable-output-redirection is used. fi TIMESTAMP_ON_OUTPUT=1 log Time stamps enabled for output. return ;; --enable-syslog) ENABLE_SYSLOG=1 return ;; --log-file) if [ $# -eq 2 ];then local MY_LOG_FILE_TEMP=$2 local MY_LOG_DIR_TEMP=$(dirname $MY_LOG_FILE_TEMP) if [ ! -d $MY_LOG_DIR_TEMP ];then log Folder $MY_LOG_DIR_TEMP does not exist. It will be created. log "$(mkdir -p $MY_LOG_DIR_TEMP)" fi log Current log file is: $MY_LOG_FILE_TEMP log Rotating the logs # We make sure that the current log file is not deleted. We change the mtime to be current time. log "$(touch $MY_LOG_FILE_TEMP)" # Find all log files that have a date appended, older than 14 days and remove them. #log "$(find $(dirname $MY_LOG_FILE_TEMP) -name $(basename $MY_LOG_FILE_TEMP)-\* -mtime +$DAYS_TO_KEEP_THE_LOG -print0|xargs -0r rm -v)" log "$(find $(dirname $MY_LOG_FILE_TEMP) -name $(basename $MY_LOG_FILE_TEMP)-\* -mtime +$DAYS_TO_KEEP_THE_LOG|xargs rm 2>/dev/null)" # rename the log file and append the current date and time to the filename. #log "$(mv -v $MY_LOG_FILE_TEMP $MY_LOG_FILE_TEMP-$(date "$FILESUFIX_DATE_FORMAT"))" log "$(echo $MY_LOG_FILE_TEMP '->' $MY_LOG_FILE_TEMP-$(date "$FILESUFIX_DATE_FORMAT");mv $MY_LOG_FILE_TEMP $MY_LOG_FILE_TEMP-$(date "$FILESUFIX_DATE_FORMAT"))" # Dump the log memory buffer into the log file. if [ "x$MY_LOG" != "x" ];then echo -e "$MY_LOG" >>$MY_LOG_FILE_TEMP unset MY_LOG fi if [[ $MY_LOG_FILE_TEMP =~ '^[^/]' ]]; then log Full path of the log is $PWD/$MY_LOG_FILE_TEMP fi MY_LOG_FILE=$MY_LOG_FILE_TEMP if [[ $OUTPUT_NOT_LOGGED != 1 ]];then if [[ $TIMESTAMP_ON_OUTPUT == 1 ]];then exec > >(while read LINE; do echo $(date "$LOG_DATE_FORMAT") ">" $LINE; done|tee -a $MY_LOG_FILE) 2>&1 else exec > >(tee -a $MY_LOG_FILE) exec 2> >(tee -a >(sed 's/^/ERR: /' >>$MY_LOG_FILE) 1>&2) fi fi return else log "Invalid number of paramaters for the log function" fi ;; --help|--*) echo 'This function allows to log inside a script. It can be used to log the entire output to a log file.' echo 'Examples:' echo ' log "Message to log"' echo ' log --log-file FILENAME.LOG' echo ' log --enable-timestamps;log --log-file FILENAME.LOG' echo ' log --disable-output-redirection;log --log-file FILENAME.LOG' echo ' log --enable-syslog' return ;; "") # If the message is empty, then do not log anything. return ;; esac # We log to the console to STDERR then to syslog. if [[ $ENABLE_SYSLOG == 1 ]];then logger -p local1.notice -t $(basename $0) -i -- "$@" fi if [ "x$MY_LOG_FILE" = "x" ]; then echo $(date "$LOG_DATE_FORMAT") "$@" >&2 # If we do not have a log file configured, we will buffer the log in memory. if [ "x$MY_LOG" = "x" ];then MY_LOG="$(date "$LOG_DATE_FORMAT") . $@" else MY_LOG="$MY_LOG\n$(date "$LOG_DATE_FORMAT") . $@" fi else if [[ $OUTPUT_NOT_LOGGED != 1 ]];then if [[ $TIMESTAMP_ON_OUTPUT == 1 ]];then echo "$@" >&2 else echo $(date "$LOG_DATE_FORMAT") "$@" >&2 fi else echo $(date "$LOG_DATE_FORMAT") "$@" >&2 echo $(date "$LOG_DATE_FORMAT") "$@" >> $MY_LOG_FILE fi fi } #}}} #vim:ts=4:sw=4:et:fdm=marker: 

这是它的用法:

 SCRIPT_HOME=$(cd $(dirname $0);pwd -P) . $SCRIPT_HOME/log-function.sh log --enable-syslog log --log-file $SCRIPT_HOME/logs/$(basename $0).log log Starting $0 script with params=$@ on $(hostname) host as $USER user.