🚀 Advanced Techniques & Best Practices
Để một shell script không chỉ chạy được mà còn phải chạy tốt—ổn định, an toàn, và dễ bảo trì—việc áp dụng các kỹ thuật nâng cao và best practices là điều không thể thiếu. Phần này sẽ giới thiệu các khái niệm quan trọng giúp bạn nâng tầm kỹ năng viết script của mình, từ xử lý lỗi chuyên sâu đến các phương pháp gỡ lỗi hiệu quả và những quy tắc vàng để script của bạn trở nên chuyên nghiệp hơn.
1. Xử Lý Lỗi Chuyên Sâu (Advanced Error Handling)
Một script chuyên nghiệp phải có khả năng dự đoán và xử lý các tình huống lỗi một cách triệt để, đảm bảo script kết thúc một cách an toàn hoặc thông báo lỗi rõ ràng, không để lại hậu quả không mong muốn cho hệ thống.
Sử dụng set
để kiểm soát hành vi của Script
Đặt các l ệnh set
ở đầu script của bạn để tăng cường sự an toàn và tính nghiêm ngặt trong quá trình thực thi:
#!/bin/bash
# Dừng script ngay lập tức nếu có bất kỳ lệnh nào trả về mã lỗi khác 0 (lỗi)
set -e
# Báo lỗi và dừng script nếu có biến chưa được định nghĩa được sử dụng
set -u
# Khiến pipeline trả về mã lỗi của lệnh cuối cùng thất bại (thay vì lệnh cuối cùng của pipeline, thường là 0)
set -o pipefail
Ví dụ:
#!/bin/bash
set -euo pipefail # Kết hợp các tùy chọn thường dùng
# Lệnh này không tồn tại, script sẽ dừng ngay tại đây do 'set -e'
non_existent_command
echo "Dòng này sẽ không bao giờ được thực thi"
Sử dụng trap
để dọn dẹp tài nguyên khi Script kết thúc
trap
là một công cụ mạnh mẽ cho phép bạn thực thi một lệnh hoặc một hàm khi script nhận được một tín hiệu (signal) cụ thể. Điều này cực kỳ hữu ích để thực hiện các tác vụ dọn dẹp (như xóa file tạm, giải phóng lock) trước khi script thoát, dù là thoát bình thường hay do lỗi.
#!/bin/bash
# trap_example.sh - Minh họa cách dùng trap để dọn dẹp
set -e # Script sẽ thoát nếu có lỗi
TEMP_FILE=$(mktemp /tmp/my_temp_file.XXXXXX)
LOCK_FILE="/var/lock/my_script.lock"
# Hàm dọn dẹp
cleanup() {
echo "Thực hiện dọn dẹp..."
rm -f "$TEMP_FILE"
rm -f "$LOCK_FILE"
echo "Dọn dẹp hoàn tất."
}
# Đặt trap để gọi hàm cleanup khi script thoát (EXIT), bị lỗi (ERR), hoặc bị ngắt (INT, TERM)
trap cleanup EXIT ERR INT TERM
# Tạo lock file để tránh chạy song song (ví dụ đơn giản)
if [ -f "$LOCK_FILE" ]; then
echo "Script đã đang chạy (phát hiện lock file)."
exit 1
fi
touch "$LOCK_FILE"
echo "Bắt đầu xử lý, file tạm được tạo tại: $TEMP_FILE"
echo "Dữ liệu quan trọng" > "$TEMP_FILE"
# Giả lập một công việc
sleep 5
# Giả lập một lỗi để kiểm tra trap
echo "Gặp lỗi mô phỏng..."
non_existent_command # Lệnh này sẽ gây lỗi, kích hoạt 'set -e' và trap ERR/EXIT
echo "Script hoàn thành (dòng này sẽ không chạy do lỗi ở trên)"
2. Kỹ Thuật Debugging Hiệu Quả
Debugging là một phần không thể thiếu trong quá trình phát triển script. Bash cung cấp một số công cụ và kỹ thuật giúp bạn tìm và sửa lỗi một cách nhanh chóng.
Dùng set -x
để theo dõi từng lệnh
Đây là cách nhanh nhất để xem chính xác những lệnh nào đang được thực thi, các đối số của chúng được mở rộng như thế nào, và giá trị của các biến tại thời điểm đó. Output sẽ được hiển thị trên stderr
, thường bắt đầu bằng dấu +
.
#!/bin/bash
# Bật chế độ debug (trace execution)
set -x
USER="admin"
HOME_DIR="/home/$USER"
echo "Kiểm tra thư mục..."
if [ -d "$HOME_DIR" ]; then
echo "Thư mục $HOME_DIR tồn tại."
fi
# Tắt chế độ debug
set +x
echo "Debug đã tắt."
Kết quả sẽ tương tự như:
+ USER=admin
+ HOME_DIR=/home/admin
+ echo 'Kiểm tra thư mục...'
Kiểm tra thư mục...
+ '[' -d /home/admin ']'
+ echo 'Thư mục /home/admin tồn tại.'
Thư mục /home/admin tồn tại.
+ set +x
Debug đã tắt.
Kiểm tra cú pháp với bash -n
Trước khi chạy một script phức tạp, bạn nên kiểm tra xem nó có lỗi cú pháp (syntax error) hay không mà không cần thực thi script. Lệnh bash -n
(noexec) sẽ đọc script và báo lỗi nếu có.
bash -n /path/to/your_script.sh
Nếu không có output nào, nghĩa là cú pháp của script hợp lệ. Nếu có lỗi, nó sẽ chỉ ra dòng và loại lỗi.
3. Best Practices cho Script Chuyên Nghiệp
Viết script không chỉ là làm cho nó chạy được, mà còn là làm cho nó dễ đọc, dễ bảo trì, an toàn và tái sử dụng được. Dưới đây là một số best practices quan trọng.