Ketika sebuah proses dimatikan dengan sinyal yang dapat ditangani seperti SIGINT
atau SIGTERM
tetapi tidak menangani sinyal, apa yang akan menjadi kode keluar dari proses?
Bagaimana dengan sinyal yang tidak dapat ditangani seperti SIGKILL
?
Dari apa yang saya tahu, mematikan proses dengan SIGINT
kemungkinan menghasilkan kode keluar 130
, tetapi apakah itu akan berbeda menurut implementasi kernel atau shell?
$ cat myScript
#!/bin/bash
sleep 5
$ ./myScript
<ctrl-c here>
$ echo $?
130
Saya tidak yakin bagaimana saya akan menguji sinyal lain…
$ ./myScript &
$ killall myScript
$ echo $?
0 # duh, that's the exit code of killall
$ killall -9 myScript
$ echo $?
0 # same problem
Jawaban yang Diterima:
Proses dapat memanggil _exit()
panggilan sistem (di Linux, lihat juga exit_group()
) dengan argumen integer untuk melaporkan kode keluar ke induknya. Meskipun bilangan bulat, hanya 8 bit paling tidak signifikan yang tersedia untuk induknya (kecuali jika menggunakan waitid()
atau handler di SIGCHLD di induk untuk mengambil kode itu, meskipun tidak di Linux).
Orang tua biasanya akan melakukan wait()
atau waitpid()
untuk mendapatkan status anak mereka sebagai bilangan bulat (meskipun waitid()
dengan semantik yang agak berbeda dapat digunakan juga).
Di Linux dan sebagian besar Unices, jika proses dihentikan secara normal, bit 8 hingga 15 dari status tersebut nomor akan berisi kode keluar yang diteruskan ke exit()
. Jika tidak, maka 7 bit paling tidak signifikan (0 hingga 6) akan berisi nomor sinyal dan bit 7 akan disetel jika sebuah inti dibuang.
perl
$?
misalnya berisi nomor itu seperti yang ditetapkan oleh waitpid()
:
$ perl -e 'system q(kill $$); printf "%04xn", $?'
000f # killed by signal 15
$ perl -e 'system q(kill -ILL $$); printf "%04xn", $?'
0084 # killed by signal 4 and core dumped
$ perl -e 'system q(exit $((0xabc))); printf "%04xn", $?'
bc00 # terminated normally, 0xbc the lowest 8 bits of the status
Kerang mirip Bourne juga membuat status keluar dari perintah yang dijalankan terakhir di $?
mereka sendiri variabel. Namun, itu tidak berisi secara langsung nomor yang dikembalikan oleh waitpid()
, tetapi transformasi di atasnya, dan itu berbeda antar shell.
Apa yang umum di antara semua shell adalah $?
berisi 8 bit terendah dari kode keluar (nomor yang diteruskan ke exit()
) jika proses dihentikan secara normal.
Dimana perbedaannya adalah ketika proses dihentikan oleh sebuah sinyal. Dalam semua kasus, dan itu diperlukan oleh POSIX, jumlahnya akan lebih besar dari 128. POSIX tidak menentukan berapa nilainya. Namun dalam praktiknya, di semua shell mirip Bourne yang saya tahu, 7 bit $?
terendah akan berisi nomor sinyal. Tapi, di mana n
adalah nomor sinyal,
-
di ash, zsh, pdksh, bash, Bourne shell,
$?
adalah128 + n
. Apa artinya di shell itu, jika Anda mendapatkan$?
dari129
, Anda tidak tahu apakah itu karena proses keluar denganexit(129)
atau apakah itu dibunuh oleh sinyal1
(HUP
pada sebagian besar sistem). Tetapi alasannya adalah bahwa shell, ketika mereka keluar sendiri, secara default mengembalikan status keluar dari perintah yang terakhir keluar. Dengan memastikan$?
tidak pernah lebih besar dari 255, yang memungkinkan untuk memiliki status keluar yang konsisten:$ bash -c 'sh -c "kill $$"; printf "%xn" "$?"' bash: line 1: 16720 Terminated sh -c "kill $$" 8f # 128 + 15 $ bash -c 'sh -c "kill $$"; exit'; printf '%xn' "$?" bash: line 1: 16726 Terminated sh -c "kill $$" 8f # here that 0x8f is from a exit(143) done by bash. Though it's # not from a killed process, that does tell us that probably # something was killed by a SIGTERM
-
ksh93
,$?
adalah256 + n
. Artinya dari nilai$?
Anda dapat membedakan antara proses yang terbunuh dan tidak terbunuh. Versiksh
yang lebih baru , saat keluar, jika$?
lebih besar dari 255, membunuh dirinya sendiri dengan sinyal yang sama agar dapat melaporkan status keluar yang sama kepada induknya. Meskipun kedengarannya seperti ide yang bagus, itu berartiksh
akan menghasilkan dump inti tambahan (berpotensi menimpa yang lain) jika proses dimatikan oleh sinyal pembangkit inti:$ ksh -c 'sh -c "kill $$"; printf "%xn" "$?"' ksh: 16828: Terminated 10f # 256 + 15 $ ksh -c 'sh -c "kill -ILL $$"; exit'; printf '%xn' "$?" ksh: 16816: Illegal instruction(coredump) Illegal instruction(coredump) 104 # 256 + 15, ksh did indeed kill itself so as to report the same # exit status as sh. Older versions of `ksh93` would have returned # 4 instead.
Di mana Anda bahkan bisa mengatakan ada bug adalah
ksh93
membunuh dirinya sendiri meskipun$?
berasal darireturn 257
dilakukan oleh suatu fungsi:$ ksh -c 'f() { return "$1"; }; f 257; exit' zsh: hangup ksh -c 'f() { return "$1"; }; f 257; exit' # ksh kills itself with a SIGHUP so as to report a 257 exit status # to its parent
-
yash
.yash
menawarkan kompromi. Ini mengembalikan256 + 128 + n
. Itu berarti kita juga dapat membedakan antara proses yang dimatikan dan proses yang dihentikan dengan benar. Dan setelah keluar, itu akan melaporkan128 + n
tanpa harus bunuh diri dan efek sampingnya.$ yash -c 'sh -c "kill $$"; printf "%xn" "$?"' 18f # 256 + 128 + 15 $ yash -c 'sh -c "kill $$"; exit'; printf '%xn' "$?" 8f # that's from a exit(143), yash was not killed
Untuk mendapatkan sinyal dari nilai $?
, cara portabel adalah dengan menggunakan kill -l
:
$ /bin/kill 0
Terminated
$ kill -l "$?"
TERM
(untuk portabilitas, Anda tidak boleh menggunakan nomor sinyal, hanya nama sinyal)
Terkait:Pencadangan tingkat byte versus tingkat file?Di bidang non-Bourne:
csh
/tcsh
danfish
sama dengan shell Bourne kecuali statusnya di$status
bukannya$?
(perhatikan bahwazsh
juga menyetel$status
untuk kompatibilitas dengancsh
(selain$?
)).rc
:status keluar ada di$status
juga, tetapi ketika dimatikan oleh sinyal, variabel itu berisi nama sinyal (sepertisigterm
atausigill+core
jika inti dihasilkan) alih-alih angka, yang merupakan bukti lain dari desain cangkang yang bagus.-
es
. status keluar bukan variabel. Jika Anda peduli, Anda menjalankan perintah sebagai:status = <={cmd}
yang akan mengembalikan angka atau
sigterm
atausigsegv+core
seperti dirc
.
Mungkin untuk kelengkapan, kita harus menyebutkan zsh
$pipestatus
dan bash
$PIPESTATUS
array yang berisi status keluar dari komponen pipeline terakhir.
Dan juga untuk kelengkapan, ketika datang ke fungsi shell dan file sumber, secara default fungsi kembali dengan status keluar dari perintah terakhir yang dijalankan, tetapi juga dapat mengatur status pengembalian secara eksplisit dengan return
bawaan Dan kami melihat beberapa perbedaan di sini:
bash
danmksh
(sejak R41, regresi^Wchange tampaknya sengaja diperkenalkan) akan memotong angka (positif atau negatif) menjadi 8 bit. Jadi misalnyareturn 1234
akan mengatur$?
ke210
,return -- -1
akan mengatur$?
ke 255.zsh
danpdksh
(dan turunan selainmksh
) mengizinkan bilangan bulat desimal 32 bit yang ditandatangani (-2 hingga 2-1) (dan potong angka menjadi 32 bit).ash
danyash
izinkan bilangan bulat positif apa pun dari 0 hingga 2-1 dan kembalikan kesalahan untuk bilangan apa pun dari itu.ksh93
untukreturn 0
untukreturn 320
setel$?
apa adanya, tetapi untuk hal lain, potong menjadi 8 bit. Hati-hati seperti yang telah disebutkan bahwa mengembalikan angka antara 256 dan 320 dapat menyebabkanksh
untuk bunuh diri saat keluar.rc
danes
izinkan mengembalikan daftar genap apa pun.
Perhatikan juga bahwa beberapa shell juga menggunakan nilai khusus $?
/$status
untuk melaporkan beberapa kondisi kesalahan yang bukan merupakan status keluar dari suatu proses, seperti 127
atau 126
untuk perintah tidak ditemukan atau tidak dapat dieksekusi (atau kesalahan sintaks dalam file sumber)…