【问题标题】:Logging functions in bash and stdoutbash 和 stdout 中的日志记录功能
【发布时间】:2011-04-01 07:09:56
【问题描述】:

我希望能够将日志消息放在 bash 函数的中间,而不会影响这些函数的输出。例如,考虑以下函数log()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

之后$values 包含字符串"Log message: Fetching animals cat dog mouse"

我应该如何修改这个脚本,使"Log message: Fetching animals"输出到终端,而$values包含"cat dog mouse"

【问题讨论】:

标签: bash logging stdout


【解决方案1】:

choroba's solution to another question 展示了如何使用 exec 打开一个新的文件描述符。

将这个问题的解决方案翻译成如下内容:

# 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

执行上述产生:

Log message: Fetching animals
Animals: cat dog mouse

有关在 Bash 中使用 I/O 重定向和文件描述符的更多信息,请访问:

【讨论】:

  • 为什么这个解决方案不是公认的解决方案?它解决了 OP 提出的确切问题。
  • 是的,这就是解决方案
【解决方案2】:

您可以使用 >&2 将输出重定向到文件句柄 2 上的 sdterr 错误文件

示例:

# 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

`` 只在 stdout 上输出,而不是在 stderr 上。另一方面,控制台同时显示两者。

如果您真的想要在标准输出上显示日志消息,您可以在分配给变量后将错误重定向回标准输出:

# 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

【讨论】:

  • 是的,我知道我可以 ...但我不想:-) 换个说法,我如何在一个脚本中处理多个标准输出?一个用于整个脚本,一个用于被调用的函数。
  • 你不能,因为没有多个stdout,只有1个。stdout和stderr的存在实际上是一种将有效负载与监控/仪器分离的模式的旧实现。获取 log() 输出以将其与有效负载分开或对其进行标记以便以后将其删除的唯一方法:例如get_animals | grep -v "^Log message:" 。在我看来,标记和删除它更糟糕。
  • 酷,好的,我会这样做的。我很希望我可以保留 stderr 用于错误输出,并使用 stdout 来记录输出。我想问题出在我的键盘和椅子之间:-)
  • 无法使用函数输出结果和注销文本。因为两者都使用 echo。
【解决方案3】:
    #
    #------------------------------------------------------------------------------
    # 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

【讨论】:

    【解决方案4】:

    您可以将日志输出重定向到标准错误流:

    log()
    {
        echo 1>&2 "Log message: $1"
    }
    

    【讨论】:

    • 是的,但我想登录到标准输出,而不是标准错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-07-06
    • 2022-10-15
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    • 2015-06-26
    • 1970-01-01
    相关资源
    最近更新 更多