Làm cách nào tôi có thể xác minh xem một quy trình đang chạy có bắt được tín hiệu hay bỏ qua hoặc chặn nó không? Lý tưởng nhất là tôi muốn xem danh sách các tín hiệu, hoặc ít nhất là không phải thực sự gửi tín hiệu để kiểm tra.
Làm cách nào tôi có thể xác minh xem một quy trình đang chạy có bắt được tín hiệu hay bỏ qua hoặc chặn nó không? Lý tưởng nhất là tôi muốn xem danh sách các tín hiệu, hoặc ít nhất là không phải thực sự gửi tín hiệu để kiểm tra.
Câu trả lời:
Trong Linux, bạn có thể tìm thấy PID của quy trình của mình, sau đó xem xét /proc/$PID/status
. Nó chứa các dòng mô tả tín hiệu nào bị chặn (SigBlk), bị bỏ qua (SigIgn) hoặc bị bắt (SigCgt).
# cat /proc/1/status
...
SigBlk: 0000000000000000
SigIgn: fffffffe57f0d8fc
SigCgt: 00000000280b2603
...
Số ở bên phải là một bitmask. Nếu bạn chuyển đổi nó từ hex sang nhị phân, mỗi 1 bit đại diện cho tín hiệu bị bắt, đếm từ phải sang trái bắt đầu bằng 1. Vì vậy, bằng cách giải thích dòng SigCgt, chúng ta có thể thấy rằng init
quá trình của tôi đang bắt được các tín hiệu sau:
00000000280b2603 ==> 101000000010110010011000000011
| | | || | || |`-> 1 = SIGHUP
| | | || | || `--> 2 = SIGINT
| | | || | |`----------> 10 = SIGUSR1
| | | || | `-----------> 11 = SIGSEGV
| | | || `--------------> 14 = SIGALRM
| | | |`-----------------> 17 = SIGCHLD
| | | `------------------> 18 = SIGCONT
| | `--------------------> 20 = SIGTSTP
| `----------------------------> 28 = SIGWINCH
`------------------------------> 30 = SIGPWR
(Tôi đã tìm thấy ánh xạ số-tên bằng cách chạy kill -l
từ bash.)
EDIT : Và theo nhu cầu phổ biến, một kịch bản, trong POSIX sh.
sigparse () {
i=0
# bits="$(printf "16i 2o %X p" "0x$1" | dc)" # variant for busybox
bits="$(printf "ibase=16; obase=2; %X\n" "0x$1" | bc)"
while [ -n "$bits" ] ; do
i="$(expr "$i" + 1)"
case "$bits" in
*1) printf " %s(%s)" "$(kill -l "$i")" "$i" ;;
esac
bits="${bits%?}"
done
}
grep "^Sig...:" "/proc/$1/status" | while read a b ; do
printf "%s%s\n" "$a" "$(sigparse "$b")"
done # | fmt -t # uncomment for pretty-printing
/proc
gì? Nó chỉ hoạt động trên Linux ... Và local
không phải là POSIX. Vâng, nó là như vậy, nhưng tác dụng của nó là "không xác định".
/bin/sh
. Bạn nói đúng local
; Tôi sẽ dọn sạch nó.
Trên Solaris, chạy psig
trên id tiến trình để nhận danh sách các tín hiệu và cách xử lý chúng.
Ví dụ:
bash-4.2$ psig $$
11088: bash
HUP caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
INT caught sigint_sighandler 0
QUIT ignored
ILL caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
TRAP caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
ABRT caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
EMT caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
FPE caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
KILL default
BUS caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
SEGV caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
SYS caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
PIPE caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
ALRM caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
TERM ignored
USR1 caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
USR2 caught termsig_sighandler 0 HUP,INT,ILL,TRAP,ABRT,EMT,FPE,BUS,SEGV,SYS,PIPE,ALRM,TERM,USR1,USR2,VTALRM,XCPU,XFSZ,LOST
CLD blocked,caught 0x4898e8 RESTART
PWR default
WINCH caught sigwinch_sighandler 0
[...]
cho thấy SIGHUP, SIGILL, v.v. đều sẽ bị bắt bởi cùng một chức năng xử lý tín hiệu termsig_sighandler
, sẽ được chạy mà không sử dụng bất kỳ cờ nào có thể được đặt qua sigaction
và tất cả các tín hiệu sẽ được che dấu tạm thời trong khi xử lý tín hiệu đang chạy (trong trường hợp này là tất cả những cái sử dụng cùng một trình xử lý tín hiệu, vì vậy nó không được nhập lại trong khi đang chạy). Bạn cũng có thể thấy SIGQUIT & SIGTERM sẽ bị bỏ qua, SIGKILL & SIGPWR sử dụng các hành động tín hiệu mặc định của hệ thống và SIGCLD chỉ định cờ RESTART, do đó, nếu trình xử lý tín hiệu của nó làm gián đoạn cuộc gọi hệ thống, tòa nhà sẽ được khởi động lại.
(Câu trả lời này tương tự như câu trả lời của @ user18096, ở chỗ nó tạo ra một tập lệnh xoay quanh câu trả lời của @ Jander's).
Tôi đã viết một psig script
để lấy một PID (hoặc tất cả các PID) và tạo đầu ra có thể đọc được của con người từ các mặt nạ tín hiệu /proc/<PID>/status
.
Ví dụ đầu ra:
% ./psig -a
[ 1] Signals Queued: 8/773737
[ 1] Signals Pending:
[ 1] Signals Pending (Shared):
[ 1] Signals Blocked:
[ 1] Signals Ignored: SIGPIPE
[ 1] Signals Caught: SIGHUP,SIGINT,SIGABRT,SIGUSR1,SIGSEGV,SIGALRM,SIGTERM,SIGCHLD,SIGPWR
...
[ 31001] Signals Queued: 0/773737
[ 31001] Signals Pending:
[ 31001] Signals Pending (Shared):
[ 31001] Signals Blocked: SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGTRAP,SIGABRT,SIGBUS,SIGFPE,SIGUSR1,SIGUSR2,SIGPIPE,SIGALRM,SIGTERM,SIGSTKFLT,SIGCHLD,SIGCONT,SIGTSTP,SIGTTIN,SIGTTOU,SIGURG,SIGXCPU,SIGXFSZ,SIGPROF,SIGWINCH,SIGIO,SIGPWR,SIGSYS,SIGRTMIN,SIGRTMIN+1,SIGRTMIN+2,SIGRTMIN+3,SIGRTMIN+4,SIGRTMIN+5,SIGRTMIN+6,SIGRTMIN+7,SIGRTMIN+8,SIGRTMIN+9,SIGRTMIN+10,SIGRTMIN+11,SIGRTMIN+12,SIGRTMIN+13,SIGRTMIN+14,SIGRTMIN+15,SIGRTMAX-14,SIGRTMAX-13,SIGRTMAX-12,SIGRTMAX-11,SIGRTMAX-10,SIGRTMAX-9,SIGRTMAX-8,SIGRTMAX-7,SIGRTMAX-6,SIGRTMAX-5,SIGRTMAX-4,SIGRTMAX-3,SIGRTMAX-2,SIGRTMAX-1,SIGRTMAX
[ 31001] Signals Ignored: SIGHUP,SIGINT,SIGQUIT,SIGPIPE,SIGXFSZ
[ 31001] Signals Caught: SIGBUS,SIGUSR1,SIGSEGV,SIGUSR2,SIGALRM,SIGTERM,SIGVTALRM
Hãy cẩn thận:
with
và OrderedDict
.Tôi tiếp tục quay lại câu trả lời hay của @ Jander với hy vọng có bộ giải mã sao chép và dán khi gặp phải vấn đề như:
user@machine:~$ grep Sig...: /proc/18475/status
SigPnd: 0000000000000000
SigBlk: fffffffe7dfbfaff
SigIgn: 0000000000001000
SigCgt: 0000000182006e47
user@machine:~$
Đoán tôi sẽ phải gõ một cái gì đó ... nói:
user@machine:~$ ruby -wn - /proc/18475/status <<'EOF'
if $_.match(/Sig(Pnd|Blk|Ign|Cgt):\s([0-9a-f]{16})/) == nil
next
end
field = $1
mask = $2.to_i(16)
names = []
Signal.list().each_pair() {
|name, number|
if number == 0
# "EXIT" => 0
next
end
if (mask & (1 << (number - 1))) == 0
next
end
names << name
}
puts("Sig#{field}: #{names.join(" | ")}")
EOF
SigPnd:
SigBlk: HUP | INT | QUIT | ILL | TRAP | IOT | ABRT | FPE | BUS | SYS | PIPE | ALRM | TERM | URG | TSTP | CONT | CHLD | CLD | TTIN | TTOU | IO | XCPU | XFSZ | PROF | WINCH | USR1 | USR2 | PWR | POLL
SigIgn: PIPE
SigCgt: HUP | INT | QUIT | BUS | SEGV | ALRM | TERM | VTALRM | USR1 | USR2
user@machine:~$
Tôi muốn nó có thể dễ đọc hơn một chút, nhưng điều đó khiến nó trở nên vụng về hơn so với tôi muốn, vì vậy, nhờ đề xuất của @ alanc, tôi sẽ lưu nó dưới dạng ~ / bin / psig.
Sử dụng điều này(liên kết bị hỏng)
thư viện này để có được thông tin về các công việc đang chạy.
Có một trường đặc biệt trong struct Job
các tín hiệu, được gọi làsigCgt
Bạn có thể sử dụng một cái gì đó như thế này:
#include"read_proc.h"
int main(void)
{
struct Root * rt=read_proc();
struct Job * jb=rt->first->job;
printf("%ull\n",jb->sigCgt);
return 0;
}
Trên FreeBSD, sử dụng procstat -i <PID>
để xem tín hiệu nào bị bỏ qua bởi quá trình. Tương tự, procstat -j <PID>
để xem tín hiệu nào bị chặn bởi các luồng xử lý. Cả hai lệnh hiển thị nếu một tín hiệu đang chờ xử lý.
Đầu ra mẫu:
$ procstat -i 38540
PID COMM SIG FLAGS
38540 nsulfd HUP -I-
38540 nsulfd INT -I-
38540 nsulfd QUIT -I-
38540 nsulfd ILL ---
38540 nsulfd TRAP ---
...
$ procstat -j 38540
PID TID COMM SIG FLAGS
38540 101220 nsulfd HUP --
38540 101220 nsulfd INT --
38540 101220 nsulfd QUIT -B
38540 101220 nsulfd ILL --
38540 101220 nsulfd TRAP --
...
Xem Procstat (1) .
SigBlk
nó cũng xuất hiện trongSigCgt
? Bởi vì bằng cách chặn nó, nó chỉ có nghĩa là tín hiệu sẽ bị phẫn nộ một lát sau phải không và có cần phải bắt không?