Функции регистрации в bash и stdout

Я хотел бы иметь возможность помещать сообщения журнала в середине функций 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".

Как мне изменить этот script так, чтобы "Log message: Fetching animals" выводился на терминал, а $values содержит "cat dog mouse"?

Ответ 1

Вы можете перенаправить вывод в файл ошибки sdterr на дескриптор файла 2, используя > & 2

пример:

# 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. С другой стороны, консоль отображает оба.

Если вы действительно хотите, чтобы сообщение журнала на stdout вы перенаправляло ошибку обратно на stdout после назначения переменной:

# 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

Ответ 2

решение choroba на другой вопрос показывает, как использовать 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 можно найти по адресу:

Ответ 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"
}