Ketika sebuah proses terbunuh 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 apa SIGKILL
?
Dari apa yang dapat saya katakan, mematikan proses dengan SIGINT
kemungkinan hasil dalam kode keluar 130
, tetapi apakah itu berbeda dengan 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
kill
signals
exit
exit-status
Cory Klein
sumber
sumber
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.&
). Kirim sinyal dari proses shell lain (di terminal lain), maka Anda dapat menggunakan$?
setelah myScript telah berakhir.Jawaban:
Proses dapat memanggil panggilan
_exit()
sistem (di Linux, lihat jugaexit_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 menggunakanwaitid()
atau menangani SIGCHLD di induk untuk mengambil kode itu , meskipun tidak di Linux).Orang tua biasanya akan melakukan
wait()
atauwaitpid()
untuk mendapatkan status anak mereka sebagai bilangan bulat (meskipunwaitid()
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 olehwaitpid()
:Shell seperti Bourne juga membuat status keluar dari perintah run terakhir dalam
$?
variabel mereka sendiri . Namun, itu tidak berisi secara langsung nomor yang dikembalikan olehwaitpid()
, 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 diteruskanexit()
) 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 manan
nomor sinyalnya,dalam abu, zsh, pdksh, bash, shell Bourne,
$?
adalah128 + n
. Apa artinya itu dalam shell itu, jika Anda mendapatkan$?
dari129
, Anda tidak tahu apakah itu karena proses keluar denganexit(129)
atau apakah itu dibunuh oleh sinyal1
(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:ksh93
,$?
adalah256 + n
. Itu berarti bahwa dari nilai$?
Anda dapat membedakan antara proses terbunuh dan tidak terbunuh. Versi yang lebih baruksh
, 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 bahwaksh
akan menghasilkan dump core tambahan (berpotensi menimpa yang lain) jika proses itu mati oleh sinyal pembangkit core:Di mana Anda bahkan bisa mengatakan ada bug adalah yang
ksh93
membunuh dirinya sendiri meskipun$?
berasal dari fungsi yangreturn 257
dilakukan:yash
.yash
menawarkan kompromi. Ia kembali256 + 128 + n
. Itu berarti kita juga dapat membedakan antara proses yang terbunuh dan proses yang diakhiri dengan benar. Dan setelah keluar, ia akan melaporkan128 + n
tanpa harus bunuh diri dan efek samping yang ditimbulkannya.Untuk mendapatkan sinyal dari nilai
$?
, cara portabel adalah dengan menggunakankill -l
:(untuk portabilitas, Anda tidak boleh menggunakan nomor sinyal, hanya nama sinyal)
Di front non-Bourne:
csh
/tcsh
danfish
sama dengan shell Bourne kecuali bahwa statusnya$status
bukan$?
(catatan yangzsh
juga mengatur$status
kompatibilitas dengancsh
(selain$?
)).rc
: status keluar$status
juga ada, tetapi ketika terbunuh oleh suatu sinyal, variabel itu berisi nama sinyal (sepertisigterm
atausigill+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:yang akan mengembalikan nomor atau
sigterm
atausigsegv+core
suka dirc
.Mungkin untuk kelengkapan, kita harus menyebutkan array
zsh
's$pipestatus
danbash
'$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
danmksh
(sejak R41, regresi ^ Wchange tampaknya diperkenalkan secara sengaja ) akan memotong angka (positif atau negatif) menjadi 8 bit. Jadi misalnyareturn 1234
akan diatur$?
ke210
,return -- -1
akan diatur$?
ke 255.zsh
danpdksh
(dan turunan selainmksh
) memungkinkan bilangan bulat desimal 32 bit yang ditandatangani (-2 31 hingga 2 31 -1) (dan memotong jumlahnya menjadi 32 bit ).ash
danyash
izinkan bilangan bulat positif dari 0 hingga 2 31 -1 dan kembalikan kesalahan untuk nomor apa pun di luar itu.ksh93
untukreturn 0
kereturn 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 menyebabkanksh
bunuh diri saat keluar.rc
danes
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, seperti127
atau126
untuk perintah yang tidak ditemukan atau tidak dapat dieksekusi (atau kesalahan sintaksis dalam file bersumber) ...sumber
an exit code to their parent
danto get the *status* of their child
. Anda telah menambahkan penekanan pada "status". Apakahexit code
dan*status*
sama? Kasus ya, apa asal memiliki dua nama? Kasus tidak sama, dapatkah Anda memberikan definisi / referensi status?exit()
. The status keluar : jumlah yang diperolehwaitpid()
yang meliputi kode keluar, nomor sinyal dan apakah ada inti dibuang. Dan nomor yang disediakan beberapa shell di salah satu variabel khusus mereka ($?
,$status
) yang merupakan transformasi dari status keluar sedemikian rupa sehingga tidak mengandung kode keluar jika ada pemutusan normal, tetapi juga membawa informasi sinyal jika prosesnya terbunuh (yang itu juga umumnya disebut status keluar ). Itu semua dijelaskan dalam jawaban saya.> 128
bagian: "Status keluar dari perintah yang diakhiri karena menerima sinyal harus dilaporkan lebih besar dari 128." pubs.opengroup.org/onlinepubs/9699919799/utilities/...[email protected]
(mulai 2015-05-06) atauXref: news.gmane.org gmane.comp.standards.posix.austin.general:10726
Ketika suatu proses keluar, ia mengembalikan nilai integer ke sistem operasi. Pada sebagian besar varian unix, nilai ini diambil modulo 256: semuanya kecuali bit orde rendah diabaikan. Status proses anak dikembalikan ke induknya melalui bilangan bulat 16-bit
Status dikembalikan oleh
wait
system call atau salah satu saudara kandungnya. POSIX tidak menentukan pengkodean yang tepat dari status keluar dan nomor sinyal; hanya menyediakanSebenarnya, tidak ada kode keluar ketika suatu proses terbunuh oleh suatu sinyal: yang ada adalah status keluar .
Dalam skrip shell, status keluar dari suatu perintah dilaporkan melalui variabel khusus
$?
. Variabel ini menyandikan status keluar dengan cara yang ambigu:$?
status keluarnya.$?
128 ditambah nomor sinyal pada kebanyakan sistem. POSIX hanya mandat yang$?
lebih besar dari 128 dalam hal ini; ksh93 menambahkan 256, bukan 128. Saya belum pernah melihat varian unix yang melakukan apa pun selain menambahkan konstanta ke nomor sinyal.Dengan demikian dalam skrip shell Anda tidak dapat mengatakan secara meyakinkan apakah suatu perintah dibunuh oleh sinyal atau keluar dengan kode status lebih besar dari 128, kecuali dengan ksh93. Sangat jarang bagi program untuk keluar dengan kode status lebih besar dari 128, sebagian karena programmer menghindarinya karena
$?
ambiguitas.SIGINT adalah sinyal 2 pada sebagian besar varian unix, sehingga
$?
128 + 2 = 130 untuk proses yang dibunuh oleh SIGINT. Anda akan melihat 129 untuk SIGHUP, 137 untuk SIGKILL, dll.sumber
$?
hanya untuk cangkang mirip Bourne. Lihat jugayash
untuk perilaku yang berbeda (tapi masih POSIX). Juga sesuai POSIX + XSI (Unix), akill -2 "$pid"
akan mengirim SIGINT ke proses, tetapi nomor sinyal yang sebenarnya mungkin bukan 2, jadi $? belum tentu 128 + 2 (atau 256 + 2 atau 384 + 2), meskipunkill -l "$?"
akan kembaliINT
, itulah sebabnya saya menyarankan portabilitas untuk tidak merujuk ke nomor itu sendiri.Itu tergantung pada cangkang Anda. Dari
bash(1)
halaman manual, bagian SHELL GRAMMAR , subbagian Perintah Sederhana :Karena
SIGINT
pada sistem Anda adalah sinyal nomor 2, nilai kembali adalah 130 ketika dijalankan di bawah Bash.sumber
signal(7)
halaman manual juga.Tampaknya menjadi tempat yang tepat untuk menyebutkan bahwa SVr4 memperkenalkan waitid () pada tahun 1989, tetapi tidak ada program penting yang tampaknya menggunakannya sejauh ini. waitid () memungkinkan untuk mengambil 32 bit penuh dari kode exit ().
Sekitar 2 bulan yang lalu, saya menulis ulang bagian tunggu / tugas kontrol dari Bourne Shell untuk menggunakan waitid () alih-alih waitpid (). Ini dilakukan untuk menghapus batasan yang menutupi kode keluar dengan 0xFF.
Antarmuka waitid () jauh lebih bersih daripada implementasi wait () sebelumnya kecuali panggilan cwait () dari UNOS dari 1980.
Anda mungkin tertarik untuk membaca halaman manual di:
http://schillix.sourceforge.net/man/man1/bosh.1.html
dan periksa bagian "Substitusi Parameter" yang saat ini menatap halaman 8.
Variabel baru .sh. * Telah diperkenalkan untuk antarmuka waitid (). Antarmuka ini tidak lagi memiliki arti ambigu untuk angka yang dikenal dengan $? dan membuat antarmuka lebih mudah.
Perhatikan bahwa Anda perlu memiliki waitid () yang sesuai dengan POSIX untuk dapat menggunakan fitur ini, jadi Mac OS X dan Linux saat ini tidak menawarkan ini, tetapi waitid () ditiru pada panggilan waitpid (), jadi pada platform non-POSIX Anda hanya akan mendapatkan 8 bit dari kode keluar.
Singkatnya: .sh.status adalah kode keluar numerik, .sh.code adalah alasan keluar numerik.
Untuk portabilitas yang lebih baik, ada: .sh.codename untuk versi tekstual dari alasan keluar, misalnya "DUMPED" dan .sh.termsig, nama tunggal untuk sinyal yang menghentikan proses.
Untuk penggunaan yang lebih baik, ada dua nilai .sh.codename yang tidak terkait keluar: "NOEXEC" dan "NOTFOUND" yang digunakan ketika suatu program tidak dapat diluncurkan sama sekali.
FreeBSD memperbaiki bug waitid () mereka dalam waktu 20 jam setelah laporan saya, Linux belum memulai dengan perbaikan mereka. Saya harap 26 tahun setelah memperkenalkan fitur ini yang ada di POSIX sekarang, semua OS akan segera mendukungnya.
sumber