GNU/Linux >> Belajar Linux >  >> Linux

Kode Keluar Default Saat Proses Dihentikan?

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, $? adalah 128 + n . Apa artinya di 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 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 , $? adalah 256 + n . Artinya dari nilai $? Anda dapat membedakan antara proses yang terbunuh dan tidak terbunuh. Versi ksh 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 berarti ksh 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 dari return 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 mengembalikan 256 + 128 + n . Itu berarti kita juga dapat membedakan antara proses yang dimatikan dan proses yang dihentikan dengan benar. Dan setelah keluar, itu akan melaporkan 128 + 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 dan fish sama dengan shell Bourne kecuali statusnya di $status bukannya $? (perhatikan bahwa zsh juga menyetel $status untuk kompatibilitas dengan csh (selain $? )).
  • rc :status keluar ada di $status juga, tetapi ketika dimatikan oleh sinyal, variabel itu berisi nama sinyal (seperti sigterm atau sigill+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 atau sigsegv+core seperti di rc .

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 dan mksh (sejak R41, regresi^Wchange tampaknya sengaja diperkenalkan) akan memotong angka (positif atau negatif) menjadi 8 bit. Jadi misalnya return 1234 akan mengatur $? ke 210 , return -- -1 akan mengatur $? ke 255.
  • zsh dan pdksh (dan turunan selain mksh ) mengizinkan bilangan bulat desimal 32 bit yang ditandatangani (-2 hingga 2-1) (dan potong angka menjadi 32 bit).
  • ash dan yash izinkan bilangan bulat positif apa pun dari 0 hingga 2-1 dan kembalikan kesalahan untuk bilangan apa pun dari itu.
  • ksh93 untuk return 0 untuk return 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 menyebabkan ksh untuk bunuh diri saat keluar.
  • rc dan es izinkan mengembalikan daftar genap apa pun.
Terkait:arduino – Apakah gcode memerlukan kode respons dari penerjemah?

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)…


Linux
  1. Kode keluar baris perintah bash didemistifikasi

  2. Proses Induk Baru Ketika Proses Induk Meninggal?

  3. Bagaimana Cara Mencari Kode Keluar Untuk Aplikasi?

  1. Mengapa Garpu Mekanisme Pembuatan Proses Default?

  2. Ketika assert() gagal, apa kode keluar programnya?

  3. Apa yang terjadi ketika sebuah benang bercabang?

  1. Linux – Kapan Saya Tidak Harus Membunuh -9 Proses?

  2. Apa yang harus dilakukan ketika Ctrl + C tidak dapat menghentikan proses?

  3. Kapan saya tidak boleh membunuh -9 proses?