Перенаправить stdout и stderr в функцию
Мне нужна помощь в отправке вывода (stdin и stdout) из системных команд в функцию bash, но при этом все еще принимается вход от аргументов. Что-то вроде следующего примера. Может кто-нибудь указать мне дорогу по правильному пути?
LogMsg()
{
DateTime=`date "+%Y/%m/%d %H:%M:%S"`
echo '*****'$DateTime' ('$QMAKESPEC'): '$1 >> "$LogFile"
echo $DateTime' ('$QMAKESPEC'): '$1
}
# Already works
LogMsg "This statement is sent directly"
# Wish I could do this:
# Capture both stdout & stderr of a system function to the logfile
# I do not presume that any of the syntax that follows is good
make 2>&1 >(LogMsg)
Ответы
Ответ 1
Для этого вы можете использовать read
bash builtin:
LogMsg()
{
read IN # This reads a string from stdin and stores it in a variable called IN
DateTime=`date "+%Y/%m/%d %H:%M:%S"`
echo '*****'$DateTime' ('$QMAKESPEC'): '$IN >> "$LogFile"
echo $DateTime' ('$QMAKESPEC'): '$IN
}
И затем используйте канал:
make 2>&1 | LogMsg
Update:
Чтобы иметь возможность использовать stdin ИЛИ аргумент в качестве ввода (согласно комментарию chepner), вы можете сделать это:
LogMsg()
{
if [ -n "$1" ]
then
IN="$1"
else
read IN # This reads a string from stdin and stores it in a variable called IN
fi
DateTime=`date "+%Y/%m/%d %H:%M:%S"`
echo '*****'$DateTime' ('$QMAKESPEC'): '$IN >> "$LogFile"
echo $DateTime' ('$QMAKESPEC'): '$IN
}
Ответ 2
Это старый поток... но я использовал его, чтобы помочь мне написать функцию журнала, которая будет выводить также несколько строк вывода команды:
# Defines function to grab a time stamp #
get_Time () { Time=$(date +%Y-%m-%d\ %H:%M:%S) ; }
write_Log()
{
get_Time
if [ -n "${1}" ]; then # If it from a "<message>" then set it
IN="${1}"
echo "${Time} ${IN}" | tee -a ${log_File}
else
while read IN # If it is output from command then loop it
do
echo "${Time} ${IN}" | tee -a ${log_File}
done
fi
}
Ответ 3
Спасибо людям, которые разместили свои ответы. Я придумал свою версию, которая будет добавлять временную метку к сообщению.
#!/bin/bash
CURRENT_PID=$$
PROCESS_NAME=$(basename $0)
LOGFILE=/var/log/backup-monitor.log
function log_message {
if [ -n "$1" ]; then
MESSAGE="$1"
echo -e "$(date -Iseconds)\t$PROCESS_NAME\t$CURRENT_PID\t$MESSAGE" | tee -a $LOGFILE
else
MESSAGE=$(tee)
echo -e "$(date -Iseconds)\t$PROCESS_NAME\t$CURRENT_PID\t$MESSAGE" | tee -a $LOGFILE
fi
}
Ответ 4
По моему мнению, тайм-аут 100 мс (-t 0.1) в команде чтения позволит LogMsg обрабатывать входные каналы и параметры без ожидания в случае отсутствия ввода.
function log(){ read -t 0.1 IN1
echo $(date "+%Y/%m/%d %H:%M:%S")' ('$QMAKESPEC'): '$IN1 $* |tee -a $LogFile ;}
#test without, with pipe , with pipe and parameters , with parameters only
log ; echo foo | log ; echo foo | log bar ; log bar
2015/01/01 16:52:17 ():
2015/01/01 16:52:17 (): foo
2015/01/01 16:52:17 (): foo bar
2015/01/01 16:52:17 (): bar
tee -a дублирует в stdout и добавляет к $LogFile
получайте удовольствие
Ответ 5
Есть два способа сделать это,
во-первых, я думаю, лучше, это создать файл bash и передать ему результат следующим образом:
make 2>&1 > ./LogMsg
второй способ - передать результат в качестве аргумента функции:
LogMsg $(make 2>&1)