Writing outputs to log file and console
在Unix Shell中,我有一个env文件(env文件定义了运行用户脚本所需的参数,例如日志文件名和路径,将输出和错误重定向到日志文件,数据库连接详细信息等),该文件将所有输出(回显消息)重定向),并使用以下代码从执行的脚本向日志文件中显示错误:
1 2 | exec 1>>${LOG_FILE} exec 2>>${LOG_FILE} |
env文件在每个脚本的开头执行。由于env文件中的上述代码,所有可能是用户输出或错误的控制台输出都将直接输出到日志文件,这正是我实际需要的。
但是我希望在控制台和日志文件中同时显示一些选择性的用户输出。但是由于上面的代码,我无法这样做。
我知道,如果删除上面的代码,在这种情况下可以得到所需的结果,但是我将不得不将所有其他输出手动写入日志文件,这并非易事。
有没有一种方法可以在不删除上述代码的情况下在控制台和日志文件中获得输出?
1 | exec 3>&1 1>>${LOG_FILE} 2>&1 |
会将stdout和stderr输出发送到日志文件,但也会使fd 3连接到控制台,因此您可以执行
1 | echo"Some console message" 1>&3 |
只向控制台写一条消息,或者
1 | echo"Some console and log file message" | tee /dev/fd/3 |
向控制台和日志文件写入消息-
例:
1 2 3 4 5 6 | exec 3>&1 1>>${LOG_FILE} 2>&1 echo"This is stdout" echo"This is stderr" 1>&2 echo"This is the console (fd 3)" 1>&3 echo"This is both the log and the console" | tee /dev/fd/3 |
会打印
1 2 | This is the console (fd 3) This is both the log and the console |
在控制台上并放
1 2 3 | This is stdout This is stderr This is both the log and the console |
进入日志文件。
是的,您想使用
tee - read from standard input and write to standard output and files
只需将命令传递到tee并将文件作为参数传递,就像这样:
1 2 | exec 1 | tee ${LOG_FILE} exec 2 | tee ${LOG_FILE} |
这既将输出打印到STDOUT,又将相同的输出写入日志文件。有关更多信息,请参见
请注意,这不会将stderr写入日志文件,因此,如果要合并两个流,请使用:
1 | exec 1 2>&1 | tee ${LOG_FILE} |
我尝试了琼蒂的答案,但我也得到了
exec: 1: not found
错误。这是最适合我的方法(确认也可以在zsh中使用):
1 2 3 4 5 6 | #!/bin/bash LOG_FILE=/tmp/both.log exec > >(tee -a ${LOG_FILE} ) exec 2> >(tee -a ${LOG_FILE} >&2) echo"this is stdout" chmmm 77 /makeError |
之后的文件/tmp/both.log包含
1 2 | this is stdout chmmm command not found |
除非您从tee中删除-a,否则将附加/tmp/both.log。
提示:
我想在stdout和日志文件上显示日志以及时间戳。上面的答案对我都不起作用。
我利用了进程替换和exec命令,并提出了以下代码。
样本日志:
1 | 2017-06-21 11:16:41+05:30 Fetching information about files in the directory... |
在脚本顶部添加以下行:
1 2 3 4 5 | LOG_FILE=script.log exec > >(while read -r line; do printf '%s %s '"$(date --rfc-3339=seconds)""$line" | tee -a $LOG_FILE; done) exec 2> >(while read -r line; do printf '%s %s '"$(date --rfc-3339=seconds)""$line" | tee -a $LOG_FILE; done >&2) |
希望这对某人有帮助!
对于日志文件,您可能需要输入日期才能输入文本数据。以下代码可能会有所帮助
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # declaring variables Logfile="logfile.txt" MAIL_LOG="Message to print in log file" Location="were is u want to store log file" cd $Location if [ -f $Logfile ] then echo"$MAIL_LOG">> $Logfile else touch $Logfile echo"$MAIL_LOG">> $Logfile fi |
输出:2.日志文件将在第一次运行时创建,并在以后的运行中继续更新。如果将来运行时缺少日志文件,脚本将创建新的日志文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | # #------------------------------------------------------------------------------ # echo pass params and print them to a log file and terminal # with timestamp and $host_name and $0 PID # usage: # doLog"INFO some info message" # doLog"DEBUG some debug message" # doLog"WARN some warning message" # doLog"ERROR some really ERROR message" # doLog"FATAL some really fatal message" #------------------------------------------------------------------------------ doLog(){ type_of_msg=$(echo $*|cut -d"" -f1) msg=$(echo"$*"|cut -d"" -f2-) [[ $type_of_msg == DEBUG ]] && [[ $do_print_debug_msgs -ne 1 ]] && return [[ $type_of_msg == INFO ]] && type_of_msg="INFO" # one space for aligning [[ $type_of_msg == WARN ]] && type_of_msg="WARN" # as well # print to the terminal if we have one test -t 1 && echo" [$type_of_msg] `date"+%Y.%m.%d-%H:%M:%S %Z"` [$run_unit][@$host_name] [$$]""$msg" # define default log file none specified in cnf file test -z $log_file && \ mkdir -p $product_instance_dir/dat/log/bash && \ log_file="$product_instance_dir/dat/log/bash/$run_unit.`date"+%Y%m"`.log" echo" [$type_of_msg] `date"+%Y.%m.%d-%H:%M:%S %Z"` [$run_unit][@$host_name] [$$]""$msg">> $log_file } #eof func doLog |
我找到了一种获取所需输出的方法。尽管这可能是一些非常规的方法。无论如何,它去了。在redir.env文件中,我有以下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #####redir.env##### export LOG_FILE=log.txt exec 2>>${LOG_FILE} function log { echo"$1">>${LOG_FILE} } function message { echo"$1" echo"$1">>${LOG_FILE} } |
然后在实际脚本中,我有以下代码:
1 2 3 4 5 6 | #!/bin/sh . redir.env echo"Echoed to console only" log"Written to log file only" message"To console and log" echo"This is stderr. Written to log file only" 1>&2 |
在此,echo输出仅输出到控制台,日志输出仅输出到日志文件,消息输出同时输出到日志文件和控制台。
执行完上面的脚本文件后,我有以下输出:
在控制台中
In console
Echoed to console only
To console and log
对于日志文件
In Log File
Written to log file only
This is stderr. Written to log file only
To console and log
希望对您有所帮助。
试试这个,它将完成工作:
1 2 3 | log_file=$curr_dir/log_file.txt exec > >(tee -a ${log_file} ) exec 2> >(tee -a ${log_file} >&2) |
我发现将stdout和stderr都附加到日志文件非常有用。我很高兴看到alfonx使用
我发现在zsh中,可以使用" multios"构造修改here-doc解决方案,以将输出复制到stdout / stderr和日志文件中:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/bin/zsh LOG=$0.log # 8 is an arbitrary number; # multiple redirects for the same file descriptor # triggers"multios" . 8<<\EOF /dev/fd/8 2>&2 >&1 2>>$LOG >>$LOG # some commands date >&2 set -x echo hi echo bye EOF echo not logged |
它不像