Перенаправить stdout и stderr в функцию - программирование

Перенаправить 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)
4b9b3361

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