ฉันจะตรวจสอบว่ากระบวนการที่กำลังทำงานอยู่จะจับสัญญาณหรือเพิกเฉยหรือบล็อกได้อย่างไร โดยหลักการแล้วฉันต้องการดูรายการสัญญาณหรืออย่างน้อยก็ไม่จำเป็นต้องส่งสัญญาณเพื่อตรวจสอบ
ฉันจะตรวจสอบว่ากระบวนการที่กำลังทำงานอยู่จะจับสัญญาณหรือเพิกเฉยหรือบล็อกได้อย่างไร โดยหลักการแล้วฉันต้องการดูรายการสัญญาณหรืออย่างน้อยก็ไม่จำเป็นต้องส่งสัญญาณเพื่อตรวจสอบ
คำตอบ:
ภายใต้ Linux คุณสามารถหา PID /proc/$PID/status
ของกระบวนการของคุณแล้วมองไปที่ มันมีเส้นที่อธิบายว่าสัญญาณใดถูกบล็อก (SigBlk), ละเว้น (SigIgn) หรือถูกจับ (SigCgt)
# cat /proc/1/status
...
SigBlk: 0000000000000000
SigIgn: fffffffe57f0d8fc
SigCgt: 00000000280b2603
...
หมายเลขทางด้านขวาคือ bitmask หากคุณแปลงจากฐานสิบหกเป็นเลขฐานสิบหกแต่ละบิตจะแทนสัญญาณที่จับได้นับจากขวาไปซ้ายเริ่มต้นด้วย 1 ดังนั้นโดยการตีความบรรทัด SigCgt เราจะเห็นว่าinit
กระบวนการของฉันจับสัญญาณต่อไปนี้:
00000000280b2603 ==> 101000000010110010011000000011
| | | || | || |`-> 1 = SIGHUP
| | | || | || `--> 2 = SIGINT
| | | || | |`----------> 10 = SIGUSR1
| | | || | `-----------> 11 = SIGSEGV
| | | || `--------------> 14 = SIGALRM
| | | |`-----------------> 17 = SIGCHLD
| | | `------------------> 18 = SIGCONT
| | `--------------------> 20 = SIGTSTP
| `----------------------------> 28 = SIGWINCH
`------------------------------> 30 = SIGPWR
(ฉันพบการทำแผนที่หมายเลขต่อชื่อโดยเรียกใช้kill -l
จาก bash)
แก้ไข : และตามความต้องการที่นิยมสคริปต์ใน 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
คืออะไร มันจะทำงานบน Linux เท่านั้น ... และlocal
ไม่ใช่ POSIX มันก็เป็นเช่นนั้น แต่ผลของมันคือ "ไม่ได้ระบุ"
/bin/sh
คือการรับประกันที่อยู่ใกล้ทันสมัยใด คุณกำลังขวาlocal
; ฉันจะทำความสะอาด
บน Solaris รันpsig
บน id กระบวนการเพื่อรับรายการสัญญาณและวิธีจัดการ
ตัวอย่างเช่น
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
[...]
ซึ่งแสดงให้เห็นว่า SIGHUP, SIGILL และอื่น ๆ ทั้งหมดจะถูกจับโดยฟังก์ชั่นจัดการสัญญาณเดียวกันtermsig_sighandler
ซึ่งจะทำงานโดยไม่ใช้ธงใด ๆ ที่สามารถตั้งค่าผ่านsigaction
และสัญญาณทั้งหมดที่จะถูกปิดบังชั่วคราวในขณะที่ตัวจัดการสัญญาณคือ ทำงาน (ในกรณีนี้ทุกคนที่ใช้ตัวจัดการสัญญาณเดียวกันดังนั้นจึงไม่ได้ถูกนำเข้าไปใหม่ในขณะที่ทำงานอยู่) คุณยังสามารถเห็นได้ว่า SIGQUIT & SIGTERM จะถูกละเว้น SIGKILL & SIGPWR ใช้การทำงานของสัญญาณเริ่มต้นของระบบและ SIGCLD ระบุการตั้งค่าสถานะ RESTART ดังนั้นหากตัวจัดการสัญญาณขัดขวางการเรียกของระบบ syscall จะเริ่มต้นใหม่
(คำตอบนี้คล้ายกับคำตอบของ @ user18096 ซึ่งจะสร้างสคริปต์รอบคำตอบของ @ Jander)
ฉันได้เขียนpsig script
จะใช้ PID (หรือ PIDs ทั้งหมด) /proc/<PID>/status
และการสร้างผลผลิตที่มนุษย์สามารถอ่านได้จากหน้ากากสัญญาณ
ตัวอย่างผลลัพธ์:
% ./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
คำเตือน:
with
OrderedDict
ฉันกลับมาที่คำตอบที่น่ารักของ @ Jander ต่อไปโดยหวังว่าจะมีตัวถอดรหัสคัดลอกและวางเมื่อต้องเผชิญกับสิ่งต่อไปนี้:
user@machine:~$ grep Sig...: /proc/18475/status
SigPnd: 0000000000000000
SigBlk: fffffffe7dfbfaff
SigIgn: 0000000000001000
SigCgt: 0000000182006e47
user@machine:~$
คิดว่าฉันจะต้องเคาะอะไรบางอย่าง ... พูดว่า:
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:~$
ฉันอยากให้มันอ่านออกได้ แต่นั่นทำให้รู้สึกงุ่มง่ามที่จะเรียกใช้มากกว่าที่ฉันต้องการขอบคุณคำแนะนำของ @ alanc ฉันจะบันทึกเป็น ~ / bin / psig
ใช้ นี้(ลิงก์เสียหาย)
ห้องสมุดนี้เพื่อรับข่าวสารเกี่ยวกับงานซึ่งกำลังทำงานอยู่
มีสนามพิเศษstruct Job
สำหรับสัญญาณเรียกว่าsigCgt
คุณอาจใช้สิ่งนี้:
#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;
}
บน FreeBSD ใช้procstat -i <PID>
เพื่อดูว่าสัญญาณใดถูกละเว้นโดยกระบวนการ ในทำนองเดียวกันprocstat -j <PID>
เพื่อดูว่าสัญญาณใดถูกบล็อกโดยเธรดกระบวนการ คำสั่งทั้งสองแสดงว่ามีสัญญาณค้างอยู่หรือไม่
ตัวอย่างผลลัพธ์:
$ 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 --
...
ดูprocstat (1)
SigBlk
มันจะปรากฏขึ้นในSigCgt
? เพราะโดยการปิดกั้นมันก็หมายความว่าสัญญาณจะไม่พอใจอีกเล็กน้อยในภายหลังและความต้องการที่จะถูกจับ?