Câu 1Cách viết nào dùng giá trị mặc định access.log khi tham số thứ nhất không được truyền?
Báo cáo tổng hợp log — Tổng kết tham số, hàm và kết hợp lệnh
Bài viết này là một phần của Khóa học Linux, giúp bạn thành thạo từ đầu những kỹ năng Linux thực tiễn, từ các lệnh cơ bản đến lập trình shell script.
Nhận log cần xử lý bằng log=${1:-access.log}, tổng hợp bằng vòng lặp for kết hợp grep -c và awk '{sum+=$1}', rồi gói tất cả vào báo cáo here-doc và mã thoát — minh họa và thực hành trên terminal.
Gộp các thành phần vào một script — bộ khung của báo cáo tổng hợp log
Tất cả những gì bạn đã học đến giờ — biến, tham số vị trí ($1), rẽ nhánh điều kiện ([ ] và if), vòng lặp (for / while), hàm (name() { } và local), đọc đầu vào (while read … done < file), kết hợp lệnh ($(...)) và đầu ra (>> và here-doc) — giờ được ghép lại trong một script thiết thực duy nhất.
Đề tài là thứ hay gặp nhất trong vận hành: "báo cáo tổng hợp log".
Một script thiết thực nhận log cần xử lý và ngưỡng qua tham số, kiểm tra đầu vào rồi tổng hợp, gom kết quả thành báo cáo, và kết thúc bằng cách trả về mã thoát.
Phần tổng hợp thì bạn kết hợp các lệnh như grep để đếm, awk để cộng tổng, sed để định dạng; gom phần lặp đi lặp lại vào hàm và vòng lặp sẽ dễ đọc hơn.
Khi tham số vị trí trống thì bù bằng giá trị mặc định ${1:-access.log}.
vi mini.sh # mở bằng trình soạn thảo, viết nội dung sau rồi lưu bằng :wq
# #!/bin/sh
# log=${1:-access.log} # giá trị mặc định khi không có tham số
# count_status() { # hàm trả về số đếm của một status code
# grep -c " $1\$" "$log"
# }
# if [ ! -f "$log" ]; then # kiểm tra đầu vào
# echo "not found: $log" >&2
# exit 1
# fi
# for s in 200 403 500; do # tổng hợp theo từng status code
# echo "$s : $(count_status $s)"
# done
# exit 0
chmod +x mini.sh
| Thành phần | Dùng ở đâu trong script này | Ví dụ |
|---|---|---|
Biến name=... | Quản lý tên log, nơi xuất ra và ngưỡng ở cùng một chỗ | log=${1:-access.log} |
Tham số $1 / ${1:-mặc định} | Nhận log cần xử lý và ngưỡng từ dòng lệnh | limit=${2:-1} |
Điều kiện [ -f f ] / if | Kiểm tra log có tồn tại và xét xem ngưỡng có bị vượt hay không | if [ ! -f "$log" ]; then exit 1; fi |
Vòng lặp for / while read | Tổng hợp theo từng status code và đọc từng dòng một | for s in 200 403 500; do … done |
Hàm name() { … } | Gom phần tổng hợp dưới một cái tên rồi tái sử dụng | count_status() { grep -c " $1\$" "$log"; } |
Đọc đầu vào while read … < f | Đọc log từng dòng một và đếm theo từng URL | while read line; do … done < "$log" |
Kết hợp $(grep -c …) / awk | Lấy số đếm và tổng vào biến bằng thay thế lệnh | n=$(grep -c ' 500$' "$log") |
Đầu ra >> / here-doc | Ghi các giá trị tổng hợp ra một báo cáo định sẵn | cat > "$out" <<REPORT … REPORT |
Đọc đầu vào rồi hoàn thiện bằng kết hợp lệnh — while read và grep / awk / sed
Phần xử lý chi tiết theo từng dòng thì làm bằng while read line; do … done < file.
Với mỗi dòng đọc được, bạn thu hẹp phạm vi dòng bằng grep, tổng hợp cột bằng awk, chuẩn hóa cách viết bằng sed. Ghép những bước đó lại bên trong một hàm thì bạn tái sử dụng được logic tổng hợp như một khối độc lập.
Chèn thêm bước định dạng như sed 's/^GET /[GET] /' thì bố cục báo cáo giữ được sự thống nhất.
Bước hoàn thiện là nhúng các giá trị tổng hợp vào báo cáo định sẵn bằng here-doc; nếu vượt ngưỡng thì nối thêm cảnh báo rồi trả exit 1, còn bình thường thì trả exit 0.
Nhận tham số thứ hai làm ngưỡng bằng ${2:-100} rồi so sánh số như if [ "$err" -gt "$limit" ], bạn có một báo cáo kèm đánh giá dùng được trong vận hành.
Bài tổng kết chính là kết hợp `grep` / `awk` / `sed` đã học ở phần cơ bản ngay bên trong các cấu trúc điều khiển của shell script.
vi scan.sh # mở bằng trình soạn thảo, viết nội dung sau rồi lưu bằng :wq
# #!/bin/sh
# log=${1:-access.log}
# limit=${2:-1}
# err=$(grep -c ' 500$' "$log") # lấy số đếm 500 bằng cách kết hợp lệnh
# while read line; do # đọc từng dòng một
# echo "$line" | sed 's/^/log: /' # định dạng rồi in ra
# done < "$log"
# if [ "$err" -gt "$limit" ]; then # xét theo ngưỡng
# echo "WARN: too many 500"; exit 1
# fi
# exit 0
chmod +x scan.sh
while read đọc vào từng dòng một, rồi kết hợp grep / awk / sed để hoàn thiện thành báo cáo kèm đánh giá.Đánh giá vượt ngưỡng hay không bằng tham số — gộp tổng hợp với mã thoát
Gộp phần nhận tham số và tổng hợp ở nửa đầu với phần đánh giá và mã thoát ở nửa sau vào một script, bạn hoàn thiện một "báo cáo kèm kết luận đạt/không đạt" dùng được trong vận hành.
Nhận ngưỡng từ tham số thứ nhất; nếu số đếm mà grep -c hay awk tổng hợp được từ ngưỡng trở lên thì coi là cảnh báo và trả exit 1, còn dưới ngưỡng thì coi là bình thường và trả exit 0.
Phía gọi phán đoán được thành hay bại qua chính mã thoát này.
Trong so sánh số, -gt nghĩa là "lớn hơn" còn -ge nghĩa là "lớn hơn hoặc bằng", nên cách xử lý giá trị đúng bằng ngưỡng sẽ khác nhau.
[ "$err" -gt "$limit" ] ở Thực hành 2 không thỏa điều kiện khi số đếm bằng đúng ngưỡng, còn [ "$err" -ge "$limit" ] ở Thực hành 3 thì cảnh báo ngay cả khi bằng nhau.
Đây là điểm then chốt quyết định đạt hay không tại biên, nên hãy chọn theo mục đích sử dụng.
-ge: từ ngưỡng trở lên thì cảnh báo và trả exit 1, dưới ngưỡng thì bình thường và trả exit 0.Kiểm tra kiến thức
Hãy trả lời từng câu hỏi một.
Câu 2Cách viết nào đọc một tệp từng dòng một rồi xử lý?
Câu 3Khi vượt ngưỡng, làm sao để báo cho phía gọi biết là có bất thường?