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

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 на что-то

Angelo
источник
Это круто, так как я читаю, вы используете 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}

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

kirikaza
источник
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команду, которые действительно полезны.

Фальк
источник
Скрипт выглядит круто, но на самом деле не делает то, что мне нужно, поведение должно изменяться во время выполнения.
Гленн