Запись выходных данных в файл журнала и консоль
в оболочке Unix у меня есть env-файл (env file определяет параметры, необходимые для запуска пользовательского скрипта, такие как имя и путь файла журнала, перенаправление выходов и ошибок в файл журнала, сведения о подключении к базе данных и т. д.), который перенаправляет все выходы (сообщения Эхо) и ошибки в файл журнала из выполненного скрипта с использованием следующего кода:
exec 1>>${LOG_FILE}
exec 2>>${LOG_FILE}
env-файл выполняется в начале каждого скрипта. Из-за вышеуказанного кода в файле env все консольные выходы, которые могут быть пользовательскими выходами или ошибками, непосредственно выводятся в файл журнала, который мне действительно нужен.
но есть некоторые выборочные пользовательские выходы, которые я хочу отображать как в консоли, так и в файле журнала. Но из-за вышеприведенного кода я не могу этого сделать.
Я знаю, что если я удалю приведенный выше код, я могу получить желаемый результат для этого случая, но мне придется вручную записать все остальные выходные данные в файл журнала, который не является простым задача.
есть ли способ получить вывод как в консоли, так и в файле журнала без удаления вышеуказанных кодов?
9 ответов:
exec 3>&1 1>>${LOG_FILE} 2>&1
отправит вывод stdout и stderr в файл журнала, но также оставит вас с FD 3, подключенным к консоли, поэтому вы можете сделать
echo "Some console message" 1>&3
написать сообщение только на консоли, или
echo "Some console and log file message" | tee /dev/fd/3
написать сообщение и консоль и файл журнала -
tee
отправляет свой вывод на оба своих собственных fd 1 (который здесьLOG_FILE
) и файл, который вы сказали ему написать (который здесь fd 3, т. е. успокаивать.)пример:
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
печати
This is the console (fd 3) This is both the log and the console
на консоль и поставить
This is stdout This is stderr This is both the log and the console
в файл журнала.
Да, вы хотите использовать
tee
:тройник-чтение из стандартного ввода и запись в стандартный вывод и файлы
просто передайте свою команду в tee и передайте файл в качестве аргумента, например:
exec 1 | tee ${LOG_FILE} exec 2 | tee ${LOG_FILE}
Это оба выводит вывод на STDOUT и записывает тот же вывод в файл журнала. Смотрите
man tee
для получения дополнительной информации.обратите внимание, что это не будет записывать stderr в файл журнала, так что если вы хотите объединить два потока, то использование:
exec 1 2>&1 | tee ${LOG_FILE}
Я попытался ответить Джунти, но я также получил
exec: 1: не найдено
ошибка. Это то, что лучше всего работает для меня (подтвердил работать в zsh тоже):
#!/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 / оба.журнал после этого содержит
this is stdout chmmm command not found
/tmp / оба.журнал добавляется, если вы не удалите из тройника.
для файла журнала вы можете ввести дату в текстовые данные. следующий код может помочь
# 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. Файл журнала будет создан в первом запуске и продолжать обновляться со следующих запусков. Если файл журнала отсутствует в будущем запуске , скрипт создаст новый файл журнала.
Я хотел отобразить журналы на stdout и файл журнала вместе с меткой времени. Ни один из ответов не работал для меня. Я использовал подмена процесса и exec команда и придумал следующий код. Примеры журналов:
2017-06-21 11:16:41+05:30 Fetching information about files in the directory...
добавить следующие строки в верхней части вашего скрипта:
LOG_FILE=script.log exec > >(while read -r line; do printf '%s %s\n' "$(date --rfc-3339=seconds)" "$line" | tee -a $LOG_FILE; done) exec 2> >(while read -r line; do printf '%s %s\n' "$(date --rfc-3339=seconds)" "$line" | tee -a $LOG_FILE; done >&2)
надеюсь, что это поможет кому-то!
Я нашел способ получить желаемый результат. Хотя это может быть несколько необычным способом. В любом случае здесь он идет. В перенаправителя.env файл у меня есть следующий код:
#####redir.env##### export LOG_FILE=log.txt exec 2>>${LOG_FILE} function log { echo "">>${LOG_FILE} } function message { echo "" echo "">>${LOG_FILE} }
тогда в самом скрипте у меня есть следующие коды:
#!/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
здесь Эхо выходы только на консоль,log выводит только файл журнала и выводит данные как в файл журнала, так и в консоль.
после выполнения указанного выше файла скрипта I есть следующие выходы:
в консоли
в консоли
Эхом откликнулся на утешение только
Чтобы утешить и войтидля файла журнала
В Файле Журнала Записывается только в файл журнала
Это поток stderr. Записывается только в файл журнала
Чтобы утешить и войтинадеюсь, что это поможет.
# #------------------------------------------------------------------------------ # echo pass params and print them to a log file and terminal # with timestamp and $host_name and 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
Я считаю очень полезным добавить как stdout, так и stderr в файл журнала. Я был рад увидеть решение alfonx с
exec > >(tee -a)
, потому что мне было интересно, как сделать это с помощьюexec
. Я наткнулся на творческое решение, используя здесь-doc синтаксис и.
: https://unix.stackexchange.com/questions/80707/how-to-output-text-to-both-screen-and-file-inside-a-shell-scriptя обнаружил, что в zsh решение here-doc можно изменить с помощью " multios" построить для копирования вывода в stdout/stderr и файл журнала:
#!/bin/zsh LOG=.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
это не так читаемо, как
exec
решение, но оно имеет то преимущество, что позволяет войти только часть сценария. Конечно, если вы опустите EOF, то весь скрипт выполняется с журналированием. Я не уверен, какzsh
реализует multios, но он может иметь меньше накладных расходов, чемtee
. К сожалению, кажется, что нельзя использовать multios сexec
.