OnWorks Linux và Windows Online WorkStations

Logo

Lưu trữ trực tuyến miễn phí cho máy trạm

<Trước | Nội dung | Tiếp theo>

Traps

Trong Chương 10, chúng ta đã thấy cách các chương trình có thể phản hồi lại các tín hiệu. Chúng tôi cũng có thể thêm khả năng này vào các tập lệnh của mình. Mặc dù các tập lệnh mà chúng tôi đã viết cho đến nay không cần đến điều kiện này (vì chúng có thời gian thực thi rất ngắn và không tạo các tệp tạm thời), các tập lệnh lớn hơn và phức tạp hơn có thể được hưởng lợi từ việc có một quy trình xử lý tín hiệu.

Khi chúng tôi thiết kế một tập lệnh lớn, phức tạp, điều quan trọng là phải xem xét điều gì sẽ xảy ra nếu người dùng đăng xuất hoặc tắt máy tính trong khi tập lệnh đang chạy. Khi một sự kiện như vậy xảy ra, một tín hiệu sẽ được gửi đến tất cả các quá trình bị ảnh hưởng. Đổi lại, các chương trình gửi lại các quá trình đó có thể thực hiện các hành động để đảm bảo việc chấm dứt chương trình một cách hợp lý và có trật tự. Ví dụ, giả sử rằng chúng tôi đã viết một tập lệnh tạo một tệp tạm thời trong quá trình thực thi của nó. Trong quá trình thiết kế tốt, chúng tôi sẽ yêu cầu tập lệnh xóa tệp khi tập lệnh hoàn thành công việc của nó. Sẽ rất thông minh nếu tập lệnh xóa tệp nếu nhận được tín hiệu cho biết rằng chương trình sẽ bị kết thúc sớm.

bash cung cấp một cơ chế cho mục đích này, được gọi là bẫy. Các bẫy được triển khai bằng lệnh nội trang được đặt tên thích hợp, bẫy. bẫy sử dụng cú pháp sau:

bẫy tín hiệu đối số [tín hiệu...]

Ở đâu đối số là một chuỗi sẽ được đọc và coi như một lệnh và tín hiệu là đặc điểm kỹ thuật của một tín hiệu sẽ kích hoạt việc thực thi lệnh được thông dịch.

Đây là một ví dụ đơn giản:



#! / bin / bash


# trap-demo: demo xử lý tín hiệu đơn giản

#! / bin / bash


# trap-demo: demo xử lý tín hiệu đơn giản


bẫy "echo" Tôi đang phớt lờ bạn. "" SIGINT SIGTERM cho tôi trong {1..5}; làm

echo "Lặp lại $ i of 5" ngủ 5

thực hiện

bẫy "echo" Tôi đang phớt lờ bạn. "" SIGINT SIGTERM cho tôi trong {1..5}; làm

echo "Lặp lại $ i of 5" ngủ 5

thực hiện


Tập lệnh này xác định một cái bẫy sẽ thực thi một bỏ lỡ mỗi khi nhận được tín hiệu SIG- INT hoặc SIGTERM trong khi tập lệnh đang chạy. Việc thực thi chương trình trông giống như thế này khi người dùng cố gắng dừng tập lệnh bằng cách nhấn Ctrl-c:


[tôi @ linuxbox ~] $ bẫy-demo

Lặp lại 1/5

Lặp lại 2/5 Tôi đang bỏ qua bạn. Lặp lại 3/5 Tôi đang bỏ qua bạn. Lặp lại 4/5

Lặp lại 5/5

[tôi @ linuxbox ~] $ bẫy-demo

Lặp lại 1/5

Lặp lại 2/5 Tôi đang bỏ qua bạn. Lặp lại 3/5 Tôi đang bỏ qua bạn. Lặp lại 4/5

Lặp lại 5/5


Như chúng ta có thể thấy, mỗi khi người dùng cố gắng làm gián đoạn chương trình, thông báo sẽ được in ra thay thế.

Việc xây dựng một chuỗi để tạo thành một chuỗi lệnh hữu ích có thể khá khó khăn, vì vậy, thông lệ thường là chỉ định một hàm shell làm lệnh. Trong ví dụ này, một hàm shell riêng biệt được chỉ định cho mỗi tín hiệu được xử lý:



#! / bin / bash

# trap-demo2: demo xử lý tín hiệu đơn giản exit_on_signal_SIGINT () {

echo "Tập lệnh bị gián đoạn." 2> & 1 lối ra 0

}


exit_on_signal_SIGTERM () {

echo "Tập lệnh đã kết thúc." 2> & 1 lối ra 0

}


bẫy exit_on_signal_SIGINT SIGINT bẫy exit_on_signal_SIGTERM SIGTERM

#! / bin / bash

# trap-demo2: demo xử lý tín hiệu đơn giản exit_on_signal_SIGINT () {

echo "Tập lệnh bị gián đoạn." 2> & 1 lối ra 0

}


exit_on_signal_SIGTERM () {

echo "Tập lệnh đã kết thúc." 2> & 1 lối ra 0

}


bẫy exit_on_signal_SIGINT SIGINT bẫy exit_on_signal_SIGTERM SIGTERM



cho tôi trong {1..5}; làm

echo "Lặp lại $ i of 5" ngủ 5

thực hiện


cho tôi trong {1..5}; làm

echo "Lặp lại $ i of 5" ngủ 5

thực hiện


Tập lệnh này có hai bẫy , một lệnh cho mỗi tín hiệu. Đến lượt mình, mỗi bẫy sẽ chỉ định một hàm shell sẽ được thực thi khi nhận được tín hiệu cụ thể. Lưu ý sự kết hợp của một ra lệnh trong từng chức năng xử lý tín hiệu. Không có ra, tập lệnh sẽ tiếp tục sau khi hoàn thành chức năng.

Khi người dùng nhấn Ctrl-c trong quá trình thực thi tập lệnh này, kết quả trông như thế này:



[tôi @ linuxbox ~] $ bẫy-demo2

Lặp lại 1/5

Lặp lại 2 trên 5 Tập lệnh bị gián đoạn.

[tôi @ linuxbox ~] $ bẫy-demo2

Lặp lại 1/5

Lặp lại 2 trên 5 Tập lệnh bị gián đoạn.


hình ảnh

Hồ sơ tạm thời

Một lý do khiến các trình xử lý tín hiệu được bao gồm trong các tập lệnh là để loại bỏ các tệp tạm thời mà tập lệnh có thể tạo để giữ các kết quả trung gian trong quá trình thực thi. Có một cái gì đó của một nghệ thuật để đặt tên cho các tệp tạm thời. Theo truyền thống, các chương trình trên hệ thống Unix giống như tạo các tệp tạm thời của chúng trong / Tmp thư mục, một thư mục được chia sẻ dành cho các tệp như vậy. Tuy nhiên, vì thư mục được chia sẻ, điều này đặt ra những lo ngại nhất định về bảo mật, đặc biệt là đối với các chương trình chạy với đặc quyền của người dùng siêu cấp. Ngoài bước rõ ràng là đặt quyền thích hợp cho các tệp được hiển thị cho tất cả người dùng của hệ thống, điều quan trọng là phải đặt tên tệp tạm thời không thể đoán trước được. Điều này tránh bị lợi dụng được gọi là cuộc tấn công tạm thời. Một cách để tạo tên không thể đoán trước (nhưng vẫn mang tính mô tả) là làm như sau:

tempfile = / tmp / $ (basename $ 0). $$. $ NGẪU NHIÊN

Thao tác này sẽ tạo một tên tệp bao gồm tên của chương trình, theo sau là ID quy trình (PID) của nó, theo sau là một số nguyên ngẫu nhiên. Tuy nhiên, lưu ý rằng $ RAN- DOM Biến shell chỉ trả về một giá trị trong phạm vi 1-32767, đây không phải là một phạm vi quá lớn theo thuật ngữ máy tính, do đó, một phiên bản duy nhất của biến không đủ để vượt qua kẻ tấn công đã xác định.



hình ảnh

Một cách tốt hơn là sử dụng mktemp chương trình (không nên nhầm lẫn với mktemp chức năng thư viện tiêu chuẩn) để đặt tên và tạo tệp tạm thời. Các mk- tạm thời chương trình chấp nhận một mẫu làm đối số được sử dụng để xây dựng tên tệp. Mẫu phải bao gồm một loạt các ký tự “X”, được thay thế bằng một số ký tự và số ngẫu nhiên tương ứng. Chuỗi ký tự “X” càng dài thì chuỗi ký tự ngẫu nhiên càng dài. Đây là một ví dụ:

tempfile = $ (mktemp /tmp/foobar.$$.XXXXXXXXXX)

Thao tác này tạo một tệp tạm thời và gán tên của nó cho biến tệp tạm thời. Các ký tự “X” trong mẫu được thay thế bằng các chữ cái và số ngẫu nhiên để tên tệp cuối cùng (trong ví dụ này, cũng bao gồm giá trị mở rộng của tham số đặc biệt $$ để lấy PID) có thể giống như:

/tmp/foobar.6593.UOZuvM6654

Đối với các tập lệnh được thực thi bởi người dùng thông thường, có thể khôn ngoan là tránh sử dụng / Tmp và tạo một thư mục cho các tệp tạm thời trong thư mục chính của người dùng, với một dòng mã như sau:

[[-d $ HOME / tmp]] || mkdir $ HOME / tmp


Điện toán đám mây hệ điều hành hàng đầu tại OnWorks: