Logging functions in bash and stdout
I'd like to be able to put log messages in the middle of bash functions, without affecting the output of those very functions. For example, consider the following functions log()
and get_animals开发者_运维百科()
:
# print a log a message
log ()
{
echo "Log message: $1"
}
get_animals()
{
log "Fetching animals"
echo "cat dog mouse"
}
values=`get_animals`
echo $values
After which $values
contains the string "Log message: Fetching animals cat dog mouse"
.
How should I modify this script so that "Log message: Fetching animals"
is outputted to the terminal, and $values
contains "cat dog mouse"
?
choroba's solution to another question shows how to use exec to open a new file descriptor.
Translating that solution to this question gives something like:
# Open a new file descriptor that redirects to stdout:
exec 3>&1
log ()
{
echo "Log message: $1" 1>&3
}
get_animals()
{
log "Fetching animals"
echo "cat dog mouse"
}
animals=`get_animals`
echo Animals: $animals
Executing the above produces:
Log message: Fetching animals
Animals: cat dog mouse
More information about using I/O redirection and file descriptors in Bash can be found at:
- Bash Guide for Beginners, section 8.2.3, Redirection and file descriptors
- Advanced Bash-Scripting Guide, Chapter 20, I/O Redirection
You can redirect the output to the sdterr error file on file handle 2 using >&2
example :
# print a log a message
log ()
{
echo "Log message: $1" >&2
}
get_animals()
{
log "Fetching animals"
echo "cat dog mouse"
}
values=`get_animals`
echo $values
the `` only take the output on stdout, not on stderr. The console on the other hand displays both.
If you really want the Log message on the stdout you can redirect error back to stdout after assigning to the variable :
# print a log a message
log ()
{
echo "Log message: $1" >&2
}
get_animals()
{
log "Fetching animals"
echo "cat dog mouse"
}
values=`get_animals` 2>&1
echo $values
#
#------------------------------------------------------------------------------
# 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
You could redirect log output to the standard error stream:
log()
{
echo 1>&2 "Log message: $1"
}
精彩评论