プロセスがリッスンしているシグナルを確認するにはどうすればよいですか?


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

いいえ、信号をキャッチする準備ができていなくてもブロックできます。シグナルをキャッチしない場合、シグナルに応じてデフォルトのアクションが発生します(通常はプロセスの終了)。さらに詳細が必要な場合は、質問を開いてください。
ジャンダー

から読み取るスクリプトのPOSIXバージョンの使用は何/procですか?Linuxでのみ動作します...そしてlocalPOSIXではありません。まあ、それはちょっとですが、その効果は「不特定」です。
クサラナナンダ

2
@Kusalananda:LinuxはBashを意味しません-たとえば、小さな組み込みプラットフォームはしばしばBusyboxを使用します-しかし、POSIX準拠は現代ののほぼ保証です/bin/sh。あなたは正しいですlocal。それをきれいにします。
ジャンダー

@Jander Fairポイント。私は、BashとLinuxに関する性急な仮定を立てることを告白します。
クサラナナンダ

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以外の答えを追加することを望んでいた。
ジャンダー

4

(この答えは、@ user18096の答えに似ていますが、@ Janderの答えの周りにスクリプトを作成します。)

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

警告:

  • これ Linux固有の回答です。
  • スクリプトを実行するには、比較的新しいPythonバージョンが必要になる場合があり、withandを使用し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;
}

したいのですが、リンクが壊れています。
マイケルフォックス

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.