killLệnh của bạn là ngược.
Giống như nhiều lệnh UNIX, các tùy chọn bắt đầu bằng dấu trừ phải đến trước, trước các đối số khác.
Nếu bạn viết
kill -INT 0
nó xem -INTtùy chọn này và gửi SIGINTđến 0( 0là một số đặc biệt có nghĩa là tất cả các quy trình trong nhóm quy trình hiện tại).
Nhưng nếu bạn viết
kill 0 -INT
Nó thấy 0, quyết định không có thêm tùy chọn, vì vậy sử dụng SIGTERMtheo mặc định. Và gửi nó cho nhóm quy trình hiện tại, giống như khi bạn đã làm
kill -TERM 0 -INT
(nó cũng sẽ cố gửi SIGTERMđến -INT, điều này sẽ gây ra lỗi cú pháp, nhưng nó sẽ gửi SIGTERMđến 0đầu tiên và không bao giờ đi xa đến thế.)
Vì vậy, kịch bản chính của bạn đang nhận được SIGTERMtrước khi nó chạy waitvà echo DONE.
Thêm vào
trap 'echo got SIGTERM' TERM
ở trên cùng, ngay sau
trap 'killall' INT
và chạy nó một lần nữa để chứng minh điều này.
Như Stephane Chazelas chỉ ra, những đứa trẻ của bạn ( process1, v.v.) sẽ SIGINTmặc định bỏ qua .
Trong mọi trường hợp, tôi nghĩ gửi SIGTERMsẽ có ý nghĩa hơn.
Cuối cùng, tôi không chắc liệu có kill -process groupđược đảm bảo đi đến trẻ em trước không. Bỏ qua các tín hiệu trong khi tắt có thể là một ý tưởng tốt.
Vì vậy, hãy thử điều này:
#!/bin/bash
trap 'killall' INT
killall() {
trap '' INT TERM # ignore INT and TERM while shutting down
echo "**** Shutting down... ****" # added double quotes
kill -TERM 0 # fixed order, send TERM not INT
wait
echo DONE
}
./process1 &
./process2 &
./process3 &
cat # wait forever