Khi nào hệ thống gửi SIGTERM đến một quy trình?


24

Chương trình máy chủ của tôi đã nhận được SIGTERM và dừng lại (với mã thoát 0). Tôi ngạc nhiên về điều này, vì tôi khá chắc chắn rằng có rất nhiều bộ nhớ cho nó. Trong những điều kiện nào linux (busybox) gửi SIGTERM đến một tiến trình?


Tôi không thể nghĩ về bất kỳ trường hợp nào khi kernel hoặc một công cụ tiêu chuẩn sẽ gửi SIGTERM đến một quy trình ngẫu nhiên. Bạn có thể cho chúng tôi biết những gì chương trình đang làm và bắt đầu như thế nào? Làm thế nào bạn tìm ra tình trạng thoát của chương trình? Bạn có thể tạo lại vấn đề? Bạn có nhật ký bạn có thể kiểm tra?
Gilles 'SO- ngừng trở thành ác quỷ'

Nó đang đọc và ghi vào một dòng nối tiếp và đang đáp ứng các yêu cầu UDP và TCP. Tôi đã gói thực thi trên một tập lệnh bash và do đó tôi biết mã thoát.
michelemarcon

1
Tài liệu Posix chỉ ra SIGTERM hoàn toàn là một sự kiện ở cấp độ người dùng. Có ai khác có thể giết chương trình máy chủ của bạn không?
shellter

3
Bạn là! Mã trả về 0 có nghĩa là một lối thoát bình thường. Nếu có SIGTERM, $?sẽ được đặt thành 143 (số tín hiệu 128 +).
Gilles 'SO- ngừng trở nên xấu xa'

1
Ngoài ra, ^ C là SIGINT, không phải SIGTERM và sẽ thoát với mã số 130.
flarn2006

Câu trả lời:


13

Tôi sẽ đăng bài này dưới dạng câu trả lời để có một số loại giải quyết nếu điều này hóa ra là vấn đề.

Trạng thái thoát là 0 nghĩa là thoát bình thường khỏi một chương trình thành công. Một chương trình thoát có thể chọn bất kỳ số nguyên nào trong khoảng từ 0 đến 255 làm trạng thái thoát của nó. Thông thường, các chương trình sử dụng các giá trị nhỏ. Các giá trị 126 trở lên được sử dụng bởi vỏ để báo cáo các điều kiện đặc biệt, vì vậy tốt nhất nên tránh chúng.

Ở cấp độ API C, các chương trình báo cáo trạng thái 16 bit¹ trạng thái mã hóa cả trạng thái thoát của chương trình và tín hiệu đã giết chết nó, nếu có.

Trong shell, trạng thái thoát của lệnh (được lưu trong $?) sẽ xác nhận trạng thái thoát thực tế của chương trình và giá trị tín hiệu: nếu một chương trình bị giết bởi tín hiệu, $?được đặt thành giá trị lớn hơn 128 (với hầu hết các shell, giá trị này là 128 cộng với số tín hiệu; ATT ksh sử dụng số tín hiệu 256 + và yash sử dụng số tín hiệu 384 +, để tránh sự mơ hồ, nhưng các vỏ khác không tuân theo).

Cụ thể, nếu $?là 0, chương trình của bạn đã thoát bình thường.

Lưu ý rằng điều này bao gồm trường hợp một quá trình nhận SIGTERM, nhưng có bộ xử lý tín hiệu cho nó, và cuối cùng thoát ra bình thường (có lẽ là hậu quả gián tiếp của tín hiệu SIGTERM, có lẽ là không).


Để trả lời câu hỏi trong tiêu đề của bạn, SIGTERM không bao giờ được hệ thống tự động gửi. Có một vài tín hiệu được gửi tự động như SIGHUP khi thiết bị đầu cuối biến mất, SIGSEGV / SIGBUS / SIGILL khi một quy trình thực hiện những việc không nên làm, SIGPIPE khi nó ghi vào đường ống / ổ cắm bị hỏng, v.v. một vài tín hiệu được gửi do nhấn phím trong thiết bị đầu cuối, chủ yếu là SIGINT cho Ctrl+ C, SIGQUIT cho Ctrl+ \và SIGTSTP cho Ctrl+ Z, nhưng SIGTERM không phải là một trong số đó. Nếu một quy trình nhận được SIGTERM, một số quy trình khác đã gửi tín hiệu đó.

¹ khoảng nói


Giải thích tốt về cách xác định trạng thái thoát khi nhận được tín hiệu. Tuy nhiên, câu trả lời này không giải quyết được câu hỏi của OP.
tiền mã hóa

1
@codeforester Tôi đã trả lời câu hỏi trong cơ thể, không phải câu hỏi trong tiêu đề. Chà, một trong những câu hỏi trong cơ thể - cho rằng nó dựa trên một sự hiểu lầm, nó hơi lộn xộn. Tôi sẽ thêm một vài từ về phần còn lại.
Gilles 'SO- ngừng trở nên xấu xa'

Điều đó phụ thuộc vào vỏ. Trong ksh93, đó là 256 + dấu hiệu, trong yash, đó là 384 + dấu hiệu
Stéphane Chazelas

Lưu ý rằng sử dụng giá trị trên 256 a la ksh không nhất thiết phải tốt hơn vì điều đó ngăn không cho nó được truyền vào exit. Cách yashtiếp cận là một sự thỏa hiệp tốt, nhưng hãy xem RC cho một cái khác. Xem thêm Mã thoát mặc định khi quá trình kết thúc?
Stéphane Chazelas

10

SIGTERM là tín hiệu thường được sử dụng để chấm dứt hành chính một quy trình.

Đó không phải là tín hiệu mà hạt nhân sẽ gửi, nhưng đó là tín hiệu mà một quá trình thường gửi để chấm dứt (một cách duyên dáng) một quy trình khác.

Đó là tín hiệu được gửi theo mặc định bởi kill, pkill, killall, fuser -k... lệnh.

Đó là tín hiệu được gửi đến daemon để ngăn chặn chúng (như khi a service some-service stop) hoặc được gửi inittrước khi tắt máy (tiếp theo là SIGKILL cho các quy trình không được quản lý để chấm dứt kịp thời theo SIGTERM).

Lưu ý rằng SIGTERM không phải là tín hiệu được gửi đi^C . Tín hiệu được gửi đi ^Clà SIGINT.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.