Proses dapat memanggil panggilan _exit()
sistem (di Linux, lihat juga exit_group()
) dengan argumen integer untuk melaporkan kode keluar ke induknya. Meskipun ini adalah bilangan bulat, hanya 8 bit paling tidak signifikan yang tersedia untuk induknya (kecuali saat menggunakan waitid()
atau menangani 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 nomor status itu akan berisi kode keluar sebagaimana diteruskan ke exit()
. Jika tidak, maka 7 bit paling tidak signifikan (0 hingga 6) akan berisi nomor sinyal dan bit 7 akan ditetapkan jika sebuah inti dibuang.
perl
's $?
misalnya mengandung nomor sebagai set oleh waitpid()
:
$ perl -e 'system q(kill $$); printf "%04x\n", $?'
000f # killed by signal 15
$ perl -e 'system q(kill -ILL $$); printf "%04x\n", $?'
0084 # killed by signal 4 and core dumped
$ perl -e 'system q(exit $((0xabc))); printf "%04x\n", $?'
bc00 # terminated normally, 0xbc the lowest 8 bits of the status
Shell seperti Bourne juga membuat status keluar dari perintah run terakhir dalam $?
variabel mereka sendiri . Namun, itu tidak berisi secara langsung nomor yang dikembalikan oleh waitpid()
, tetapi suatu transformasi di atasnya, dan itu berbeda antara shell.
Apa yang umum di antara semua shell adalah yang $?
berisi 8 bit terendah dari kode keluar (nomor yang diteruskan exit()
) jika proses diakhiri secara normal.
Perbedaannya adalah ketika proses diakhiri oleh sinyal. Dalam semua kasus, dan itu diperlukan oleh POSIX, angkanya akan lebih besar dari 128. POSIX tidak menentukan berapa nilainya. Namun dalam praktiknya, di semua cangkang mirip Bourne yang saya tahu, 7 bit terendah $?
akan berisi nomor sinyal. Tapi, di mana n
nomor sinyalnya,
dalam abu, zsh, pdksh, bash, shell Bourne, $?
adalah 128 + n
. Apa artinya itu dalam shell itu, jika Anda mendapatkan $?
dari 129
, Anda tidak tahu apakah itu karena proses keluar dengan exit(129)
atau apakah itu dibunuh oleh sinyal 1
( HUP
pada kebanyakan 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 "%x\n" "$?"'
bash: line 1: 16720 Terminated sh -c "kill \$\$"
8f # 128 + 15
$ bash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?"
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
, $?
adalah 256 + n
. Itu berarti bahwa dari nilai $?
Anda dapat membedakan antara proses terbunuh dan tidak terbunuh. Versi yang lebih baru ksh
, saat keluar, jika $?
lebih besar dari 255, membunuh dirinya sendiri dengan sinyal yang sama agar dapat melaporkan status keluar yang sama ke induknya. Sementara itu terdengar seperti ide yang bagus, itu berarti bahwa ksh
akan menghasilkan dump core tambahan (berpotensi menimpa yang lain) jika proses itu mati oleh sinyal pembangkit core:
$ ksh -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
ksh: 16828: Terminated
10f # 256 + 15
$ ksh -c 'sh -c "kill -ILL \$\$"; exit'; printf '%x\n' "$?"
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 yang ksh93
membunuh dirinya sendiri meskipun $?
berasal dari fungsi yang return 257
dilakukan:
$ 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. Ia kembali 256 + 128 + n
. Itu berarti kita juga dapat membedakan antara proses yang terbunuh dan proses yang diakhiri dengan benar. Dan setelah keluar, ia akan melaporkan 128 + n
tanpa harus bunuh diri dan efek samping yang ditimbulkannya.
$ yash -c 'sh -c "kill \$\$"; printf "%x\n" "$?"'
18f # 256 + 128 + 15
$ yash -c 'sh -c "kill \$\$"; exit'; printf '%x\n' "$?"
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)
Di front non-Bourne:
csh
/ tcsh
dan fish
sama dengan shell Bourne kecuali bahwa statusnya $status
bukan $?
(catatan yang zsh
juga mengatur $status
kompatibilitas dengan csh
(selain $?
)).
rc
: status keluar $status
juga ada, tetapi ketika terbunuh oleh suatu sinyal, variabel itu berisi nama sinyal (seperti sigterm
atau sigill+core
jika suatu inti dihasilkan) alih-alih sebuah angka, yang merupakan bukti lain dari desain shell yang bagus. .
es
. status keluar bukan variabel. Jika Anda peduli, Anda menjalankan perintah sebagai:
status = <={cmd}
yang akan mengembalikan nomor atau sigterm
atau sigsegv+core
suka di rc
.
Mungkin untuk kelengkapan, kita harus menyebutkan array zsh
's $pipestatus
dan bash
' $PIPESTATUS
yang berisi status keluar dari komponen pipa terakhir.
Dan juga untuk kelengkapan, ketika datang ke fungsi shell dan file sumber, secara default fungsi kembali dengan status keluar dari menjalankan perintah terakhir, tetapi juga dapat mengatur status pengembalian secara eksplisit dengan return
builtin. Dan kita melihat beberapa perbedaan di sini:
bash
dan mksh
(sejak R41, regresi ^ Wchange tampaknya diperkenalkan secara sengaja ) akan memotong angka (positif atau negatif) menjadi 8 bit. Jadi misalnya return 1234
akan diatur $?
ke 210
, return -- -1
akan diatur $?
ke 255.
zsh
dan pdksh
(dan turunan selain mksh
) memungkinkan bilangan bulat desimal 32 bit yang ditandatangani (-2 31 hingga 2 31 -1) (dan memotong jumlahnya menjadi 32 bit ).
ash
dan yash
izinkan bilangan bulat positif dari 0 hingga 2 31 -1 dan kembalikan kesalahan untuk nomor apa pun di luar itu.
ksh93
untuk return 0
ke return 320
set $?
seperti, tapi untuk hal lain, truncate untuk 8 bit. Hati-hati seperti yang telah disebutkan bahwa mengembalikan nomor antara 256 dan 320 dapat menyebabkan ksh
bunuh diri saat keluar.
rc
dan es
memungkinkan mengembalikan apa pun daftar genap.
Perhatikan juga bahwa beberapa shell juga menggunakan nilai khusus dari $?
/ $status
untuk melaporkan beberapa kondisi kesalahan yang bukan status keluar dari suatu proses, seperti 127
atau 126
untuk perintah yang tidak ditemukan atau tidak dapat dieksekusi (atau kesalahan sintaksis dalam file bersumber) ...
killall myScript
karya Anda , maka kembalinya killall (dan bukan skrip!) adalah 0. Anda bisa menempatkankill -x $$
[x menjadi nomor sinyal, dan $$ biasanya diperluas oleh shell ke PID skrip itu (berfungsi di sh, bash, ...)] di dalam skrip dan kemudian tes apa inti keluarnya.