Як я можу перевірити, які сигнали слухає процес?


81

Як я можу перевірити, чи буде запущений процес вловлювати сигнал, або ігнорувати його чи блокувати? В ідеалі я хотів би побачити список сигналів або, принаймні, не потрібно насправді надсилати сигнал для перевірки.

Відповіді:


109

У Linux ви можете знайти PID свого процесу, а потім переглянути /proc/$PID/status. Він містить рядки, що описують, які сигнали блокуються (SigBlk), ігноруються (SigIgn) або виловлюються (SigCgt).

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

Цифра праворуч - бітова маска. Якщо перетворити його з шістнадцяткової у двійкову, кожен 1-бітний представляє спійманий сигнал, рахуючи справа наліво, починаючи з 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.)

EDIT : І за популярним попитом, сценарій, в 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
Якщо сигнал вказаний у розділі SigBlk, він також відображається в SigCgt? Тому що, заблокувавши це, це просто означає, що сигнал буде відрегульований трохи пізніше, правда, і потребує спіймання?
CMCDragonkai

Ні, ви можете заблокувати сигнал, не готові його вловити. Якщо ви не вловите сигнал, дія за замовчуванням буде відбуватися залежно від сигналу (зазвичай це припинення процесу). Якщо ви хочете детальніше, вам слід відкрити питання.
Джандер

Від чого використовують POSIX версію сценарію для читання /proc? Він буде працювати тільки в Linux ... І localце не POSIX. Добре, що це так, але його ефект "не визначений".
Kusalananda

2
@Kusalananda: Linux не має на увазі Bash - наприклад, невеликі вбудовані платформи часто використовують Busybox - але відповідність POSIX є майже гарантією будь-якого сучасного /bin/sh. Ви маєте рацію local; Я приберу це.
Джандер

@Jander Fair point. Признаюсь, я зробив поспішне припущення щодо Bash та Linux.
Kusalananda

23

У програмі Solaris запустіть psigідентифікатор процесу, щоб отримати список сигналів та способи їх обробки.

Наприклад:

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, тому, якщо його обробник сигналів перерве системний виклик, системний виклик буде відновлений.


Дивовижно! Я сподівався, що хтось додасть відповідь, яка не є Linux.
Джандер

4

(Ця відповідь схожа на відповідь @ user18096, оскільки вона створює сценарій навколо відповіді @ Джандера.)

Я написав а, psig scriptщоб взяти PID (або всі PID) та створити читабельний для людини вихід із сигнальних масок /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

Застереження:

  • Це є конкретною відповіддю Linux.
  • Можливо, для запуску сценарію потрібна відносно нова версія Python, яку він використовує withта OrderedDict.

2

Я продовжую повертатися до гарної відповіді @ Джандера, сподіваючись на декодер копіювання та вставки, стикаючись з подібним:

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.


2

Використовуйте це(посилання розірвано) ця бібліотека, щоб отримати інформацію про виконані завдання.

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

Я б хотів, але посилання розірвана.
Майкл Фокс

1
@MichaelFox дивись мою редакцію. Користувач видалив свій акаунт. Нове посилання вказує на той самий проект
LittleByBlue

1

У 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) .

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.