Unix / Linux - Signals and Traps
Xin chào các nhà pháp sư máy tính tương lai! Hôm nay, chúng ta sẽ khám phá thế giới kỳ diệu của các tín hiệu và bẫy trong Unix/Linux. Đừng lo lắng nếu bạn là người mới bắt đầu lập trình - Tôi sẽ hướng dẫn bạn từng bước trong chuyến phiêu lưu này, giống như tôi đã làm cho hàng trăm sinh viên trong những năm dạy học của mình. Vậy, hãy cùng nhau bắt đầu hành trình thú vị này nhé!
What are Signals?
Hãy tưởng tượng bạn đang ở trong một nhà bếp餐厅 nhộn nhịp. Đầu bếp (giả sử gọi là Đầu bếp Unix) cần phải giao tiếp với nhân viên của mình nhanh chóng. Thay vì la hét qua tiếng ồn, ông sử dụng một hệ thống các手势. Đó chính là tín hiệu trong thế giới Unix/Linux - một cách để các tiến trình giao tiếp nhanh chóng và hiệu quả.
Các tín hiệu là các ngắt phần mềm được gửi đến một chương trình để cho biết một sự kiện quan trọng đã xảy ra. Các sự kiện này có thể từ yêu cầu của người dùng đến các sự kiện chạy thời gian ngoại lệ.
List of Signals
Giống như Đầu bếp Unix có thể có các手势 khác nhau cho "thêm muối", "nhanh lên", hoặc "nghỉ ngơi", hệ thống Unix/Linux cũng có nhiều tín hiệu khác nhau cho các mục đích khác nhau. Hãy nhìn vào một số tín hiệu phổ biến nhất:
Signal Name | Signal Number | Description |
---|---|---|
SIGHUP | 1 | Hangup detected on controlling terminal or death of controlling process |
SIGINT | 2 | Interrupt from keyboard (Ctrl+C) |
SIGQUIT | 3 | Quit from keyboard (Ctrl+) |
SIGKILL | 9 | Kill signal (cannot be caught or ignored) |
SIGTERM | 15 | Termination signal |
SIGSTOP | 17, 19, 23 | Stop the process (cannot be caught or ignored) |
Default Actions
Khi một tín hiệu được gửi đến một tiến trình, tiến trình sẽ thực hiện hành động mặc định unless được hướng dẫn khác. Những hành động mặc định này giống như phản ứng bản năng của nhân viên nhà bếp. Ví dụ:
- Kết thúc tiến trình
- Bỏ qua tín hiệu
- Dump core
- Dừng tiến trình
- Tiếp tục tiến trình đã dừng
Sending Signals
Bây giờ, hãy học cách gửi các tín hiệu này. Trong Unix/Linux, chúng ta sử dụng lệnh kill
để gửi tín hiệu đến các tiến trình. Đừng để tên lệnh làm bạn lầm tưởng - kill
không phải lúc nào cũng kết thúc tiến trình; nó chỉ là cách để gửi tín hiệu.
Dưới đây là cách bạn có thể sử dụng nó:
kill -signal_name process_id
Ví dụ, để gửi tín hiệu SIGTERM đến tiến trình 1234:
kill -SIGTERM 1234
Hoặc, sử dụng số hiệu tín hiệu:
kill -15 1234
Trapping Signals
Nếu như nhân viên nhà bếp có thể quyết định cách phản ứng với các手势 của Đầu bếp Unix thay vì luôn theo phản ứng mặc định, đó chính là điều mà bắt bẫy tín hiệu cho phép trong lập trình.
Trong các script shell, chúng ta sử dụng lệnh trap
để bắt tín hiệu và xác định điều gì sẽ làm khi tín hiệu được nhận. Dưới đây là cú pháp cơ bản:
trap "command" signal(s)
Hãy nhìn vào một ví dụ:
#!/bin/bash
trap "echo Bonjour!" SIGINT SIGTERM
echo "It's a trap!"
while true
do
sleep 60
done
Trong script này, nếu nó nhận được SIGINT hoặc SIGTERM, nó sẽ in ra "Bonjour!" thay vì kết thúc. Giống như nói với nhân viên nhà bếp, "Khi đầu bếp手势 để dừng, nói 'Bonjour!' thay vì thực sự dừng lại."
Cleaning Up Temporary Files
Một ứng dụng phổ biến của bẫy tín hiệu là dọn dẹp các tệp tạm trước khi script kết thúc. Dưới đây là một ví dụ:
#!/bin/bash
# Create a temporary file
temp_file=$(mktemp)
# Set up a trap to remove the temporary file on exit
trap "rm -f $temp_file" EXIT
# Use the temporary file
echo "Hello, World!" > $temp_file
cat $temp_file
# The temporary file will be automatically removed when the script exits
Script này tạo một tệp tạm, ghi vào nó, đọc từ nó, và sau đó tự động xóa nó khi script kết thúc, thanks to the trap.
Ignoring Signals
Đôi khi, bạn có thể muốn bỏ qua một số tín hiệu. Trong ví dụ nhà bếp, điều này sẽ giống như nói với đầu bếp, "Dù bạn手势 bao nhiêu lần để thêm muối, tôi cũng không thêm nữa!"
Dưới đây là cách bạn có thể bỏ qua một tín hiệu:
trap "" SIGINT
Lệnh này nói với script không làm gì khi nhận được tín hiệu SIGINT.
Resetting Traps
Nếu bạn muốn quay lại hành vi mặc định sau khi bắt bẫy một tín hiệu, bạn có thể đặt lại bẫy như sau:
trap - SIGINT
Điều này loại bỏ bẫy cho SIGINT, quay lại hành vi mặc định.
Dưới đây là một ví dụ hoàn chỉnh hơn:
#!/bin/bash
# Initially, trap SIGINT
trap "echo You can't stop me!" SIGINT
echo "Try to stop me with Ctrl+C..."
sleep 10
# Now, reset the trap
trap - SIGINT
echo "Okay, now you can stop me with Ctrl+C..."
sleep 10
echo "If you see this, you didn't stop me!"
Script này đầu tiên bắt SIGINT, sau đó đặt lại bẫy sau 10 giây. Giống như nói với nhân viên nhà bếp, "Bỏ qua手势 dừng trong 10 giây, sau đó quay lại bình thường."
Và đó là tất cả, các bạn! Chúng ta đã cùng nhau đi qua vùng đất của các tín hiệu và bẫy trong Unix/Linux. Nhớ rằng, thực hành làm cho hoàn hảo. Hãy thử viết các script của riêng bạn, chơi với các tín hiệu khác nhau, và sớm bạn sẽ trở thành một nhạc trưởng của các tiến trình như một true maestro. Chúc các bạn lập trình vui vẻ!
Credits: Image by storyset