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é!

Unix / Linux - Signals and Traps

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ụ:

  1. Kết thúc tiến trình
  2. Bỏ qua tín hiệu
  3. Dump core
  4. Dừng tiến trình
  5. 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