перенаправление и лог вывод скрипта


8

Я пытаюсь привести в порядок следующие фрагменты, цели разработки - записать все выходные данные из скрипта и не должны быть оберткой. Чем меньше строк, тем лучше.

Меня не волнует пользовательский ввод (на данном этапе), целевые скрипты запускаются не в интерактивном режиме.

Фрагмент должен

  • выводить стандартный вывод в журнал и всегда выводить его на консоль
  • выводить stderr в лог и эхо в консоль, если включена отладка
  • Сообщения stderr должны иметь префикс с отметками времени и другой полезностью

На данный момент у меня есть следующее, которое тестируется только в последних версиях bash (4.2+?), Как в Ubuntu, но плохо работает на CentOS6.

DEBUG_LOG="${0##*/}.log"

# copy stdout to log always and echo to console
exec >  >(tee -a ${DEBUG_LOG})           

# copy stderr to log only, unless debugging is enabled
[ $DEBUG_TEST = "true" ] \
  && exec 2> >(tee -a ${DEBUG_LOG} >&2) \
  || exec 2>> ${DEBUG_LOG}

Тогда это ...

# Expand escaped characters, wrap at 70 chars on spaces, 
# and indent wrapped lines
msg_log() { 
  echo -e "$(date +%T) ${0##*/}: $1" \
    | fold -w70 -s | sed '2~1s/^/  /' >&2; 
}
msg_con() { 
  if [ "${DEBUG_TEST}" = "true" ]; then 
    msg_log "$1"
  else
    echo -e "$1" | fold -w70 -s | sed '2~1s/^/  /'; 
  fi
}

Вместо того , что echoя могу назвать одну из этих процедур MSG, например, msg_con "hello world".
Также выходной сценарий будет затем перейти к STDERR, установив в качестве переменной среды во время вызова, например,  DEBUG_TEST=true myscript.

Я читал, что exec может не работать в некоторых оболочках, таких как busybox. На странице https://stackoverflow.com/a/5200754 есть комбинация mkfifo и fork, которая делает нечто подобное, но я бы предпочел не использовать fork без крайней необходимости.

Предпочитайте примеры bash, но то, что работает под sh или является более переносимым, было бы неплохо. Любые идеи?

Ответы:


1
function startLogging {
    exec > >(gawk -v pid=$$ '{ print strftime("%F-%T"),pid,$0; fflush(); }' | tee -a $logfile)
    [ ! -z "$DEBUG" ] && exec 2>&1 || exec 2> >(gawk -v pid=$$ '{ print strftime("%F-%T"),pid,$0; fflush(); }' >>$logfile)
    echo "=== Log started for $$ at $(date +%F-%T) ==="
}

Вам нужно установить $ logfile на что-то


Это круто, так как я читаю, вы используете gawk для добавления заголовков сообщений. Это будет иметь дополнительный побочный эффект, добавляя их и к выводам команд.
Гленн

Причина использования gawk для добавления метки времени (и идентификатора процесса) к каждой строке журнала заключается в том, что она будет выполняться каждый раз при записи выходных данных и, следовательно, обновлять метку времени. Также важно использовать gawk, а не awk, потому что я думаю, что функция strftime является расширением GNU.
Анджело

0

exec > filenameдолжен работать в sh, и он действительно работает в busybox v1.15.3 (ноябрь 2011). Но подстановка процесса >(command)непереносима, так как это расширение bash. Просто не используйте его в скриптах. Почему >>тебе не достаточно?

exec 1>>${DEBUG_LOG}
exec 2>>${DEBUG_LOG}

Другое решение - указать перенаправление вне ваших сценариев. Когда ваш скрипт вызывается в фоновом режиме (cron или системный скрипт и т. Д.), Они должны вызываться так

./my_script 1>>${DEBUG_LOG} 2>>${DEBUG_LOG}

Когда вы вызываете скрипт вручную и хотите увидеть вывод, просто вызовите его без перенаправлений.


1
Лицо, задающее вопрос, хочет, чтобы выходные данные сценария передавались как в консоль, так и в файл журнала.

0

Эти два примера сделают то, что ваши заявленные цели

echo -n $(date) >> $DEBUG_LOG
command 2>&1 | tee -a $DEBUG_LOG

или

echo -n $(date) >> $DEBUG_LOG
command >> $DEBUG_LOG 2>&1

0

Вы можете использовать teeкоманду или scriptкоманду, которые действительно полезны.


Скрипт выглядит круто, но на самом деле не делает то, что мне нужно, поведение должно изменяться во время выполнения.
Гленн
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.