Bagaimana saya bisa memeriksa sinyal apa yang sedang didengarkan suatu proses?


81

Bagaimana saya bisa memverifikasi apakah proses yang berjalan akan menangkap sinyal, atau mengabaikannya, atau memblokirnya? Idealnya saya ingin melihat daftar sinyal, atau setidaknya tidak harus benar-benar mengirim sinyal untuk memeriksa.

Jawaban:


109

Di Linux, Anda dapat menemukan PID proses Anda, lalu lihat /proc/$PID/status. Ini berisi garis yang menggambarkan sinyal mana yang diblokir (SigBlk), diabaikan (SigIgn), atau ditangkap (SigCgt).

# cat /proc/1/status
...
SigBlk: 0000000000000000
SigIgn: fffffffe57f0d8fc
SigCgt: 00000000280b2603
...

Angka di sebelah kanan adalah bitmask. Jika Anda mengonversinya dari hex ke biner, setiap 1-bit mewakili sinyal yang ditangkap, dihitung dari kanan ke kiri mulai dari 1. Jadi dengan menginterpretasikan garis SigCgt, kita dapat melihat bahwa initproses saya menangkap sinyal berikut:

00000000280b2603 ==> 101000000010110010011000000011
                     | |       | ||  |  ||       |`->  1 = SIGHUP
                     | |       | ||  |  ||       `-->  2 = SIGINT
                     | |       | ||  |  |`----------> 10 = SIGUSR1
                     | |       | ||  |  `-----------> 11 = SIGSEGV
                     | |       | ||  `--------------> 14 = SIGALRM
                     | |       | |`-----------------> 17 = SIGCHLD
                     | |       | `------------------> 18 = SIGCONT
                     | |       `--------------------> 20 = SIGTSTP
                     | `----------------------------> 28 = SIGWINCH
                     `------------------------------> 30 = SIGPWR

(Saya menemukan pemetaan angka-ke-nama dengan menjalankan kill -ldari bash.)

EDIT : Dan dengan permintaan populer, skrip, dalam 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

2
Jika sinyal terdaftar di bawah SigBlkapakah itu juga muncul SigCgt? Karena dengan memblokirnya, itu hanya berarti sinyal akan dikirim kembali sedikit kemudian, dan perlu ditangkap?
CMCDragonkai

Tidak, Anda dapat memblokir sinyal tanpa siap untuk menangkapnya. Jika Anda tidak menangkap sinyal, tindakan default akan terjadi tergantung pada sinyal (biasanya proses penghentian). Jika Anda ingin lebih detail, Anda harus membuka pertanyaan.
Jander

Apa gunanya versi dari pembacaan skrip POSIX /proc? Ini hanya akan bekerja di Linux ... Dan localbukan POSIX. Yah, memang agak, tapi efeknya "tidak ditentukan".
Kusalananda

2
@ Kusalananda: Linux tidak menyiratkan Bash - misalnya, platform tertanam yang kecil sering menggunakan Busybox - tetapi kepatuhan POSIX adalah jaminan yang dekat untuk setiap modern /bin/sh. Anda benar tentang local; Saya akan membersihkannya.
Jander

@Jander Fair point. Saya mengaku membuat asumsi tergesa-gesa tentang Bash dan Linux.
Kusalananda

23

Di Solaris, jalankan psigid proses untuk mendapatkan daftar sinyal dan cara penanganannya.

Misalnya:

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
[...]

yang menunjukkan bahwa SIGHUP, SIGILL, dll. semuanya akan ditangkap oleh fungsi pengendali sinyal yang sama termsig_sighandler, yang akan dijalankan tanpa menggunakan salah satu flag yang dapat diatur melalui sigaction, dan semua sinyal yang akan ditutup sementara untuk sementara pengendali sinyal berjalan (dalam hal ini semua yang menggunakan penangan sinyal yang sama, sehingga tidak dimasukkan kembali saat sudah berjalan). Anda juga dapat melihat bahwa SIGQUIT & SIGTERM akan diabaikan, SIGKILL & SIGPWR menggunakan aksi sinyal standar sistem, dan SIGCLD menentukan flag RESTART, jadi jika pengendali sinyal menginterupsi panggilan sistem, syscall akan dimulai kembali.


Luar biasa! Saya berharap seseorang akan menambahkan jawaban non-Linux.
Jander

4

(Jawaban ini mirip dengan jawaban @ user18096, karena ia membuat skrip di sekitar jawaban @ Jander.)

Saya telah menulis psig scriptuntuk mengambil PID (atau semua PID) dan membuat output yang dapat dibaca manusia dari masker sinyal /proc/<PID>/status.

Contoh output:

% ./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

Peringatan:

  • Ini adalah jawaban khusus Linux.
  • Mungkin perlu versi Python yang relatif baru untuk menjalankan skrip, menggunakan withdan OrderedDict.

2

Saya terus kembali ke @ Jander's jawaban cantik berharap untuk decoder copy-and-paste ketika dihadapkan dengan seperti:

user@machine:~$ grep Sig...: /proc/18475/status
SigPnd: 0000000000000000
SigBlk: fffffffe7dfbfaff
SigIgn: 0000000000001000
SigCgt: 0000000182006e47
user@machine:~$ 

Kira saya harus mengetuk sesuatu ... katakan:

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:~$ 

Saya ingin itu agak terbaca, tapi itu membuatnya lebih mudah untuk diminta daripada yang saya inginkan, jadi, berkat saran @ alanc, saya akan menyimpannya sebagai ~ / bin / psig.


2

Menggunakan ini(tautan rusak) perpustakaan ini untuk mendapatkan info tentang pekerjaan yang sedang berjalan.

Ada bidang khusus struct Jobuntuk sinyal, yang disebutsigCgt

Anda dapat menggunakan sesuatu seperti ini:

#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;
}

Saya ingin tetapi tautannya terputus.
Michael Fox

1
@MichaelFox lihat edit saya. Pengguna telah menghapus akunnya. Tautan baru menunjuk ke proyek yang sama
LittleByBlue

1

Pada FreeBSD, gunakan procstat -i <PID>untuk melihat sinyal mana yang diabaikan oleh proses. Demikian pula, procstat -j <PID>untuk melihat sinyal mana yang diblokir oleh utas proses. Kedua perintah menunjukkan jika sinyal tertunda.

Output sampel:

$ 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 -- ...

Lihat procstat (1) .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.