Lướt mạng quốc gia, tôi bắt gặp một bài báo thú vị (mà tôi mang đến đây bằng văn bản vì nó được giải thích một cách thành thạo) nơi tác giả của nó chỉ cho chúng ta cách làm cho các tập lệnh Bash của chúng ta mạnh mẽ hơn bằng cách sử dụng Traps.
Làm cho các tập lệnh bash của bạn mạnh mẽ hơn với các bẫy
Hãy tưởng tượng rằng bạn có một tập lệnh bash chạy mỗi ngày mỗi sáu giờ và tại một thời điểm nào đó nó bị lỗi hoặc cùng một tập lệnh đó chạy hai lần đồng thời. Hai tình huống này khá khó chịu vì chúng yêu cầu sự can thiệp của con người để sửa chữa hoặc vào một số thời điểm nhất định chúng không thể được giải quyết, khiến hệ thống ở trạng thái không nhất quán. Giải pháp cho điều này, trong số những cách khác, là sử dụng bẫy.
Bẫy là một cách đơn giản và hiệu quả để kiểm soát đầu ra của các tập lệnh bash. Hãy quay lại cùng một tình huống ban đầu, nếu tập lệnh bị dừng theo cách thủ công, ví dụ như với ctrl-c, nó bị gián đoạn trả lại tín hiệu đầu ra
INT
và nếu nó kết thúc bằng
kill
thì đầu ra sẽ là
TERM
.
Tất cả các mã thoát khả thi có thể được xem với
kill -l
Tuy nhiên, được sử dụng nhiều nhất chính xác là
INT, HẠN, THOÁT
Ví dụ: nếu tập lệnh bao gồm đồng bộ hóa tệp với
rsync
điều hợp lý nhất là dựa vào tệp khóa không cho phép tập lệnh chạy đồng thời:
LOCK = "/ var / run / rsync.lock" nếu [! -e $ LOCK]; sau đó chạm vào thanh foo $ LOCK rsync -avz rm $ LOCK khác echo "rsync đã chạy" fi
Trong tiếng Tây Ban Nha đơn giản, tập lệnh trên kiểm tra xem tệp khóa có tồn tại hay không và nếu nó không tồn tại, nó sẽ tạo ra nó và sau đó thực hiện lệnh tương ứng, cuối cùng là xóa tệp khóa. Nếu tệp tồn tại, tập lệnh chỉ cần gửi một thông báo đến người dùng cho biết rằng lệnh đã được chạy.
Tuy nhiên, khi có vấn đề xảy ra, tập tin khóa không được loại bỏ, làm hỏng các tác dụng không mong muốn. Giải pháp này rất đơn giản:
LOCK = "/ var / run / rsync.lock" nếu [! -e $ LOCK]; sau đó bẫy "rm -f $ LOCK; thoát" INT TERM EXIT chạm vào $ LOCK rsync -avz foo bar rm $ LOCK trap - INT TERM EXIT else echo "rsync đã chạy" fi
Điểm đặc biệt của giải pháp này là lệnh được bao bọc trong một cái bẫy để khi nhận được tín hiệu
INT, HẠN, THOÁT
tập lệnh dừng và xóa tệp khóa.
Điều đáng nói là có thể có một tình huống cạnh tranh trong kịch bản ở trên giữa thời gian tệp khóa được xác minh và thời điểm nó được tạo. Một giải pháp khả thi là sử dụng chế độ noclobber chuyển hướng và bash không chuyển hướng đến tệp hiện có:
LOCK = "/ var / run / rsync.lock" if (set -o noclobber; echo $$> "$ LOCK") 2> / dev / null; sau đó bẫy 'rm -f "$ LOCK"; thoát $? ' INT TERM EXIT rsync -avz foo bar rm -f $ LOCK trap - INT TERM EXIT else echo "rsync đã chạy: $ (cat $ LCK)" fi
Điểm đặc biệt của cái sau là nó được sử dụng như tôi đã nói, chế độ noclobber và tệp khóa chứa PID của quá trình đang được thực thi.
Cũng cần nhắc lại rằng còn có các giải pháp khác như
flock
o
solo
tuy nhiên trong bài đăng này, tôi muốn chia sẻ các giải pháp với các tài nguyên riêng của bash. Bạn có thể tìm hiểu thêm một chút về Bẫy với cái này hướng dẫn tuyệt vời.
Tuyệt quá! Cám ơn vì đã chia sẻ.
Bài viết hay, chỉ cần thay đổi 'echo "rsync đã chạy: $ (cat $ LCK)"' thành 'echo "rsync đã chạy: $ (cat $ LOCK)"'
Liên quan
Một bài báo rất thú vị, vâng thưa ông! Cái này tôi giữ.
Đó là một lệnh rất hữu ích cần ghi nhớ. Tôi đã sử dụng nó trong một tập lệnh mà tôi đã xuất bản trong một bài đăng, để xóa một số tệp mà tập lệnh đã tạo khi nó bị dừng.
Rất thú vị, vâng thưa ông.