Jawaban Glenn adalah jawaban yang bagus - perbedaan antara ( ... )
dan { ... }
penting.
Salah satu strategi yang sering saya gunakan untuk output kesalahan seperti apa yang ada di pertanyaan Anda adalah tee
perintah. Anda dapat melakukan sesuatu seperti ini:
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"
The tee
perintah akan mengirim output ke dua tempat; -a
opsi "menambahkan" output ke file bernama, dan perintah juga akan meneruskan input ke stdout. Pada >&2
akhir baris mengarahkan pengalihan tee
ke stderr, yang dapat ditangani secara berbeda (yaitu dalam pekerjaan cron).
Satu tip lain yang sering saya gunakan dalam skrip shell adalah untuk mengubah perilaku debug atau output verbose berdasarkan apakah skrip berjalan pada terminal atau memiliki -v
opsi yang disediakan. Sebagai contoh:
#!/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
Skrip dapat dimulai dengan sesuatu yang generik seperti ini di bagian atas, dengan output Verbose dan Debug tercecer di seluruh skrip. Ini hanya satu cara untuk melakukannya - ada banyak, dan orang yang berbeda akan memiliki cara mereka sendiri untuk menangani hal ini, terutama jika mereka sudah ada beberapa saat. :)
Satu lagi opsi adalah menangani output Anda dengan "handler" - fungsi shell yang dapat melakukan lebih banyak hal cerdas. Sebagai contoh:
#!/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"
(Perhatikan bahwa ${var^^}
hanya bash.)
Ini menciptakan fungsi shell yang dapat menggunakan syslog
fungsi sistem Anda (dengan logger
perintah ) to send things to system logs. The
logme () `fungsi dapat digunakan baik dengan opsi yang menghasilkan satu baris data log, atau dengan beberapa baris input yang diproses pada stdin. Main dengannya jika tampaknya menarik.
Perhatikan bahwa ini adalah contoh dan mungkin tidak boleh disalin kata demi kata kecuali Anda memahaminya dan tahu bahwa itu tepat apa yang Anda butuhkan. Ide yang lebih baik adalah mengambil konsep di sini dan mengimplementasikannya sendiri dalam skrip Anda sendiri.