Bir işlemin hangi sinyalleri dinlediğini nasıl kontrol edebilirim?


81

Çalışan bir işlemin bir sinyal alacağını, görmezden geleceğini veya engelleyeceğini nasıl doğrulayabilirim? İdeal olarak bir sinyal listesi görmek isterdim, veya en azından kontrol etmek için sinyali göndermesi gerekmez.

Yanıtlar:


109

Linux altında, işleminizin PID'sini bulabilir, sonra bakabilirsiniz /proc/$PID/status. Hangi sinyallerin bloke edildiğini (SigBlk), yok sayıldığını (SigIgn) veya yakalandığını (SigCgt) tanımlayan satırları içerir.

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

Sağdaki sayı bir bit maskesidir. Onaltılıdan ikiliye dönüştürürseniz, her 1-bit yakalanan bir sinyali gösterir, sağdan sola 1 ile başlar. Böylece SigCgt çizgisini yorumlayarak, işlemimin initaşağıdaki sinyalleri yakaladığını görebiliriz :

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

(Sayı-adı eşlemesini kill -lbash kodundan çalıştırarak buldum .)

EDIT : Popüler talebe göre bir senaryo, 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
Bir sinyal altında listeleniyorsa SigBlk, içinde de görünüyor SigCgtmu? Çünkü onu bloke ederek, sinyalin bir süre sonra doğru olarak yeniden sindirileceği ve yakalanması gerekebileceği anlamına mı geliyor?
CMCDragonkai

Hayır, bir sinyali yakalamaya hazır olmadan engelleyebilirsiniz. Bir sinyal almazsanız, sinyale bağlı olarak varsayılan bir eylem gerçekleşir (genellikle işlem sonlandırması). Daha fazla ayrıntı istiyorsanız, bir soru açmanız gerekir.
Jander

Bir betiğin okuduğu bir POSIX sürümünün kullanımı nedir /proc? Sadece Linux üzerinde çalışacak ... localPOSIX değil. Eh, biraz, ama etkisi "belirtilmemiş" dir.
Kusalananda

2
@Kusalananda: Linux, Bash anlamına gelmez - örneğin, küçük gömülü platformlar genellikle Busybox kullanır - ancak POSIX uyumluluğu, herhangi bir modern için yakın bir garantidir /bin/sh. Haklısın local; Onu temizleyeceğim.
Jander,

@Jander Fuar noktası. Bash ve Linux hakkında aceleci bir varsayımda bulunduğumu itiraf ediyorum.
Kusalananda

23

Solaris'te, psigsinyallerin ve nasıl ele alınacaklarının listesini almak için işlem kimliğini çalıştırın .

Örneğin:

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, vb. hepsinin, aynı sinyal işleyici işlevi tarafından yakalanacağını termsig_sighandler, bunlar, ayarlanabilecek bayrakların hiçbiri kullanılmadan çalıştırılacağını sigactionve sinyal işleyicisi iken geçici olarak maskelenecek olan tüm sinyallerin yakalanacağını gösterir. koşuyor (bu durumda aynı sinyal işleyicisini kullananlar, bu nedenle zaten çalışırken yeniden girilmezler). Ayrıca, SIGQUIT ve SIGTERM'in göz ardı edileceğini, SIGKILL ve SIGPWR'nin sistem varsayılan sinyal eylemlerini kullandığını ve SIGCLD'nin RESTART bayrağını belirttiğini görebilirsiniz;


Korku veren! Birinin Linux olmayan bir cevap ekleyeceğini umuyordum.
Jander,

4

(Bu cevap @ user18096'nın cevabına benzer, çünkü @ Jander'ın cevabı etrafında bir komut dosyası oluşturur.)

psig scriptBir PID (veya tüm PID'ler) almak ve içindeki sinyal maskelerinden insan tarafından okunabilir bir çıktı oluşturmak için yazdım /proc/<PID>/status.

Örnek çıktı:

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

Uyarılar:

  • Bu ise Linux belirli bir cevap.
  • Komut dosyasını çalıştırmak için nispeten yeni bir Python sürümüne ihtiyaç duyabilir, kullanır withve kullanır OrderedDict.

2

@ Jander'ın şu şekilde karşılaştığı zaman bir kopyala ve yapıştır kod çözücüsü için umut vermeyi sürdürdüğüm güzel cevabını almaya devam ediyorum:

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

Sanırım bir şeyi parçalamak zorunda kalacağım ...

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

Biraz okunaklı olmasını istedim, ama bu benim istediğimden daha fazla çağırmak için biraz hantallaştı, bu yüzden, @ alanc'ın önerisi sayesinde ~ / bin / psig olarak kaydedeceğim.


2

kullanım bu(bağlantı koptu) bu kitaplık, çalışmakta olan işler hakkında bilgi almak için.

Özel bir alan vardır struct Jobsinyaller çağrısındasigCgt

Bunun gibi bir şey kullanabilirsiniz:

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

Çok isterdim ama bağlantı koptu.
Michael Fox,

1
@MichaelFox düzenlememi gör. Kullanıcı hesabını silmiş. Yeni bağlantı aynı projeye işaret ediyor
LittleByBlue

1

FreeBSD'de, procstat -i <PID>hangi sinyallerin işlem tarafından göz ardı edildiğini görmek için kullanın . Benzer şekilde, procstat -j <PID>hangi sinyallerin işlem iplikleri tarafından bloke edildiğini görmek için. Her iki komut da bir sinyal beklemede olup olmadığını gösterir.

Örnek çıktı:

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

Bkz procstat (1) .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.