Ответ Гленна хороший - различие между ( ... )
и { ... }
важно.
Одна из стратегий, которую я часто использую для вывода ошибок, например, в вашем вопросе, это tee
команда Вы могли бы сделать что-то вроде этого:
echo "Normal output"
{
printf "[%s] %s\n" "$(date '+%Y-%m-%d %T')" "Warning text"
printf "[%s] %s\n" "$(date '+%Y-%m-%d %T')" "This event is logged."
} | tee -a $logfile >&2
echo "More normal output"
Команда tee
отправит вывод в два места; -a
опция «добавляет» вывод в именованный файл, и команда также передает ввод в стандартный вывод. В >&2
конце строки перенаправляет tee
stdout в stderr, который может обрабатываться по-разному (например, в задании cron).
Еще один совет, который я часто использую в сценариях оболочки, - это изменение поведения отладочной или подробной информации в зависимости от того, выполняется ли сценарий на терминале или имеет -v
опцию. Например:
#!/bin/sh
# Set defaults
if [ -t 0 ]; then
Verbose=true; vflag="-v"
else
Verbose=false; vflag=""
fi
Debug=false; AskYN=true; Doit=true
# Detect options (altering defaults)
while getopts vdqbn opt; do
case "$opt" in
v) Verbose=true; vflag="-v" ;; # Verbose mode
d) Debug=true; Verbose=true; vflag="-v" ;; # Very Verbose
q) Verbose=false; vflag="" ;; # quiet mode (non-verbose)
b) AskYN=false ;; # batch mode
n) Doit=false ;; # test mode
*) usage; exit 1 ;;
esac
done
# Shift our options for further processing
shift $(($OPTIND - 1))
$Verbose && echo "INFO: Verbose output is turned on." >&2
$Debug && echo "INFO: In fact, expect to be overrun." >&2
# Do your thing here
if $AskYN; then
read -p "Continue? " choice
case "$choice" in
Y|y) $Doit && somecommand ;;
*) echo "Done." ;;
esac
fi
Сценарии могут начинаться с чего-то общего, подобного этому, сверху, с подробным и отладочным выводом, разбросанным по всему сценарию. Это всего лишь один из способов сделать это - их много, и у разных людей будет свой собственный способ справиться с этим, особенно если они уже давно. :)
Еще один вариант - обработать вывод с помощью «обработчика» - функции оболочки, которая может делать более умные вещи. Например:
#!/bin/bash
logme() {
case "${1^^}" in
[IN]*) level=notice ;;
W*) level=warning ;;
A*) level=alert ;;
E*) level=emerg ;;
*) level=notice ;;
esac
if [[ "$#" -eq 1 ]]; then
# Strip off unnecessary prefixes like "INFO:"
string="${1#+([A-Z])?(:) }"
else
shift
string="$@"
fi
logger -p "${facility}.${level}" -t "$(hostname -s)" "$string"
}
echo "Normal output"
logme INFO "Here we go..."
somecommand | logme
echo "Additional normal output"
(Обратите внимание, что ${var^^}
только для bash.)
Это создает функцию оболочки, которая может использовать функции вашей системы syslog
(с logger
командой ) to send things to system logs. The
logme () `функция может использоваться либо с опциями, которые генерируют отдельные строки данных журнала, либо с несколькими строками ввода, которые обрабатываются в stdin. Поиграйте с ней, если она кажется привлекательным
Обратите внимание, что это пример, и, вероятно, его не следует копировать дословно, если вы не понимаете его и не знаете, что он делает именно то, что вам нужно. Лучшая идея - взять концепции и реализовать их самостоятельно в своих собственных сценариях.