프로세스가 듣고있는 신호를 어떻게 확인할 수 있습니까?


81

실행중인 프로세스가 신호를 포착하거나 무시하거나 차단하는지 어떻게 확인할 수 있습니까? 이상적으로 신호 목록을 보거나 적어도 실제로 신호를 보내 확인하지 않아도됩니다.

답변:


109

Linux에서는 프로세스의 PID를 찾은 다음를 참조하십시오 /proc/$PID/status. 여기에는 차단 된 신호 (SigBlk), 무시 (SigIgn) 또는 포착 (SigCgt)를 설명하는 행이 포함됩니다.

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

오른쪽의 숫자는 비트 마스크입니다. 16 진수에서 2 진수로 변환하면 각 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 -lbash에서 실행하여 번호 대 이름 매핑을 찾았습니다 .)

편집 : 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

아닙니다. 신호를 잡을 준비없이 신호를 차단할 수 있습니다. 신호를 잡지 않으면 신호에 따라 기본 동작이 발생합니다 (일반적으로 프로세스 종료). 더 자세한 정보를 원하면 질문을 열어야합니다.
Jander

에서 POSIX 버전의 스크립트를 사용하는 것은 무엇입니까 /proc? Linux에서만 작동합니다 ... localPOSIX는 아닙니다. 글쎄, 그것은 다소 있지만, 그 효과는 "지정되지 않았습니다".
Kusalananda

2
@Kusalananda : Linux는 Bash를 암시하지 않습니다. 예를 들어 소형 임베디드 플랫폼은 종종 Busybox를 사용합니다 /bin/sh. 당신이 맞습니다 local; 정리하겠습니다.
Jander

@Jander Fair 포인트. Bash와 Linux에 대한 성급한 가정을 고백합니다.
Kusalananda

23

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이 다시 시작됩니다.


대박! 누군가 Linux가 아닌 답변을 추가하기를 바랐습니다.
Jander

4

(이 답변은 @Jander의 답변 주위에 스크립트를 생성한다는 점에서 @ user18096의 답변과 유사합니다.)

나는 psig scriptPID (또는 모든 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

주의 사항 :

  • 이것은 이다 리눅스 특정 대답.
  • 스크립트를 실행하는 데 상대적으로 새로운 파이썬 버전을해야 할 수도 있습니다, 그것은 사용 with하고 OrderedDict.

2

나는 다음과 같은 상황에 직면 할 때 복사 및 붙여 넣기 디코더를 기대하면서 @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로 저장합니다.


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

나는 사랑하지만 링크가 끊어졌습니다.
Michael Fox

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)을 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.