Câu trả lời của Glenn là một câu trả lời hay - sự khác biệt giữa ( ... )
và { ... }
quan trọng.
Một chiến lược tôi thường sử dụng cho đầu ra lỗi như những gì trong câu hỏi của bạn là tee
lệnh. Bạn có thể làm một cái gì đó như thế này:
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"
Các tee
lệnh sẽ gửi ra hai nơi; -a
tùy chọn "nối" đầu ra vào tệp đã đặt tên và lệnh cũng sẽ chuyển đầu vào cùng với thiết bị xuất chuẩn. Phần >&2
cuối của dòng chuyển hướng tee
của stdout đến stderr, có thể được xử lý khác nhau (nghĩa là trong một công việc định kỳ).
Một mẹo khác mà tôi thường sử dụng trong các kịch bản shell là thay đổi hành vi của đầu ra gỡ lỗi hoặc dài dòng dựa trên việc tập lệnh đang chạy trên thiết bị đầu cuối hay có -v
tùy chọn được cung cấp. Ví dụ:
#!/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
Các tập lệnh có thể bắt đầu với một cái gì đó chung chung như thế này ở đầu, với đầu ra Verbose và Debug nằm rải rác trong tập lệnh. Đó chỉ là một cách để làm điều đó - có rất nhiều, và những người khác nhau sẽ có cách riêng để xử lý công cụ này, đặc biệt là nếu họ đã ở đây một thời gian. :)
Thêm một lựa chọn nữa là xử lý đầu ra của bạn bằng "handler" - một hàm shell có thể làm những việc thông minh hơn. Ví dụ:
#!/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"
(Lưu ý rằng chỉ ${var^^}
có bash.)
Điều này tạo ra một hàm shell có thể sử dụng các syslog
chức năng của hệ thống của bạn (với logger
lệnh ) to send things to system logs. The
logme () `có thể được sử dụng với các tùy chọn tạo một dòng dữ liệu nhật ký hoặc với nhiều dòng đầu vào được xử lý trên stdin. Chơi với nó nếu nó được xử lý có vẻ hấp dẫn
Lưu ý rằng đây là một ví dụ và có lẽ không nên sao chép nguyên văn trừ khi bạn hiểu nó và biết rằng nó thực hiện chính xác những gì bạn cần. Một ý tưởng tốt hơn là lấy các khái niệm ở đây và tự thực hiện chúng trong các kịch bản của riêng bạn.