Apakah ada kode status keluar standar di Linux?

308

Suatu proses dianggap telah selesai dengan benar di Linux jika status keluarnya adalah 0.

Saya telah melihat bahwa kesalahan segmentasi sering mengakibatkan status keluar dari 11, meskipun saya tidak tahu apakah ini hanya konvensi tempat saya bekerja (aplikasi yang gagal seperti itu semuanya internal) atau standar.

Apakah ada kode keluar standar untuk proses di Linux?

Nathan Fellman
sumber
6
jika Anda mencari hal yang disebut "nomor kesalahan sistem" yang dikembalikan oleh fungsi sistem lihat di sini di errno
marinara

Jawaban:

86

8 bit dari kode kembali dan 8 bit dari jumlah sinyal pembunuhan dicampur menjadi satu nilai pada pengembalian dari wait(2)& co. .

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>

int main() {
    int status;

    pid_t child = fork();
    if (child <= 0)
        exit(42);
    waitpid(child, &status, 0);
    if (WIFEXITED(status))
        printf("first child exited with %u\n", WEXITSTATUS(status));
    /* prints: "first child exited with 42" */

    child = fork();
    if (child <= 0)
        kill(getpid(), SIGSEGV);
    waitpid(child, &status, 0);
    if (WIFSIGNALED(status))
        printf("second child died with %u\n", WTERMSIG(status));
    /* prints: "second child died with 11" */
}

Bagaimana Anda menentukan status keluar? Secara tradisional, shell hanya menyimpan kode pengembalian 8-bit, tetapi menetapkan bit tinggi jika proses dihentikan secara tidak normal.

$ sh -c 'keluar 42'; echo $?
42
$ sh -c 'kill -SEGV $$'; echo $?
Kesalahan segmentasi
139
$ expr 139 - 128
11

Jika Anda melihat hal lain selain ini, maka program tersebut mungkin memiliki SIGSEGVpengendali sinyal yang kemudian memanggil dengan exitnormal, sehingga sebenarnya tidak terbunuh oleh sinyal. (Program dapat memilih untuk menangani sinyal selain SIGKILLdan SIGSTOP.)

singkat
sumber
8
Mengingat cara pertanyaan itu sekarang muncul, ini tampaknya bukan jawaban yang paling berguna (dan dengan demikian diterima).
David J.
332

Bagian 1: Panduan Script Bash Lanjutan

Seperti biasa, Panduan Skrip Bash Lanjutan memiliki informasi hebat : (Ini ditautkan dalam jawaban lain, tetapi ke URL non-kanonik.)

1: Catchall untuk kesalahan umum
2: Penyalahgunaan builtins shell (menurut dokumentasi Bash)
126: Perintah yang dipanggil tidak dapat mengeksekusi
127: "perintah tidak ditemukan"
128: Argumen tidak valid untuk keluar dari
128 + n: Sinyal kesalahan fatal "n"
255: Keluar status di luar kisaran (keluar hanya membutuhkan argumen integer dalam kisaran 0 - 255)

Bagian 2: sysexits.h

Referensi ABSG sysexits.h.

Di Linux:

$ find /usr -name sysexits.h
/usr/include/sysexits.h
$ cat /usr/include/sysexits.h

/*
 * Copyright (c) 1987, 1993
 *  The Regents of the University of California.  All rights reserved.

 (A whole bunch of text left out.)

#define EX_OK           0       /* successful termination */
#define EX__BASE        64      /* base value for error messages */
#define EX_USAGE        64      /* command line usage error */
#define EX_DATAERR      65      /* data format error */
#define EX_NOINPUT      66      /* cannot open input */    
#define EX_NOUSER       67      /* addressee unknown */    
#define EX_NOHOST       68      /* host name unknown */
#define EX_UNAVAILABLE  69      /* service unavailable */
#define EX_SOFTWARE     70      /* internal software error */
#define EX_OSERR        71      /* system error (e.g., can't fork) */
#define EX_OSFILE       72      /* critical OS file missing */
#define EX_CANTCREAT    73      /* can't create (user) output file */
#define EX_IOERR        74      /* input/output error */
#define EX_TEMPFAIL     75      /* temp failure; user is invited to retry */
#define EX_PROTOCOL     76      /* remote error in protocol */
#define EX_NOPERM       77      /* permission denied */
#define EX_CONFIG       78      /* configuration error */

#define EX__MAX 78      /* maximum listed value */
Schof
sumber
5
Perhatikan bahwa dalam beberapa rasa unix, beberapa perintah menggunakan status keluar 2 untuk menunjukkan hal-hal lain. Sebagai contoh, banyak implementasi grep menggunakan status keluar 2 untuk menunjukkan kesalahan, dan menggunakan status keluar 1 berarti bahwa tidak ada garis yang dipilih ditemukan.
NamshubWriter
3
Pada BSD ada halaman manual yang merangkum info dari sysexits.h:man sysexits
georgebrock
6
Apa yang dikatakan @NamshubWriter. Status keluar 2 adalah tujuan universal untuk penggunaan baris perintah yang salah dalam utilitas Unix, tidak hanya dalam "beberapa rasa unix" tetapi secara umum. Header yang ditunjukkan dalam jawaban ini tidak mencerminkan konvensi yang sebenarnya, sekarang atau ketika itu ditulis pada tahun 1987.
alexis
ABS tidak "bagus". Silakan baca tentang masalah ini; tidak sulit menemukan kritik.
tripleee
Tapi di mana kode sumber resmi yang sebenarnya untuk sysexits.h? The halaman manual semua orang terus referensi hanya prosa. Sebagai contoh referensi EX_OKtetapi tidak benar-benar mendefinisikannya dengan cara normatif seperti kode lainnya. Apakah ada lagi yang hilang?
Garret Wilson
71

'1' >>> Catchall untuk kesalahan umum

'2' >>> Penyalahgunaan bawaan shell (menurut dokumentasi Bash)

'126' >>> Perintah yang dipanggil tidak bisa dijalankan

'127' >>> "perintah tidak ditemukan"

'128' >>> Argumen tidak valid untuk keluar

'128 + n' >>> Sinyal kesalahan fatal "n"

'130' >>> Script diakhiri oleh Control-C

'255' >>> Keluar status di luar jangkauan

Ini untuk bash. Namun, untuk aplikasi lain, ada berbagai kode keluar.

segfault
sumber
1
Sepertinya kalian berdua menjawab di menit yang sama. Tian harus cukup cepat untuk melihat tautan Anda dan menempelkannya.
Nathan Fellman
6
Perhatikan bahwa 'kontrol-C menghasilkan 130' konsisten dengan '128 + n' untuk sinyal n; control-C menghasilkan SIGINT yang merupakan sinyal 2.
Jonathan Leffler
3
Ini tampaknya dijiplak dari ABS tanpa atribusi. (Kami dapat memberi tahu karena ABS berisi informasi yang salah atau setidaknya menyesatkan.)
tripleee
4
Ini adalah kode keluar RESERVED, menurut Panduan Script Bash Lanjutan . Itu berarti nilai-nilai ini karenanya harus dihindari untuk parameter keluar yang ditentukan pengguna .
ingyhere
53

Tidak ada jawaban yang lebih lama yang menggambarkan status keluar 2 dengan benar. Bertentangan dengan apa yang mereka klaim, status 2 adalah apa yang sebenarnya dikembalikan utilitas baris perintah Anda ketika dipanggil dengan tidak benar. (Ya, jawabannya bisa berusia sembilan tahun, memiliki ratusan upvotes, dan masih salah.)

Berikut adalah konvensi status keluar lama yang nyata untuk pemutusan normal, yaitu bukan dengan sinyal:

  • Status keluar 0: sukses
  • Keluar status 1: "gagal", seperti yang didefinisikan oleh program
  • Keluar status 2: kesalahan penggunaan baris perintah

Misalnya, diffmengembalikan 0 jika file yang diperbandingkannya identik, dan 1 jika berbeda. Dengan konvensi lama, program unix kembali keluar Status 2 saat dipanggil tidak benar (pilihan tidak diketahui, nomor yang salah dari argumen, dll) Sebagai contoh, diff -N, grep -Yatau diff a b cakan semua hasil di $?menjadi set ke 2. Ini adalah dan telah menjadi praktek sejak hari-hari awal Unix di tahun 1970-an.

The jawaban yang diterima menjelaskan apa yang terjadi ketika sebuah perintah diakhiri oleh sinyal. Singkatnya, pengakhiran karena sinyal yang tidak tertangkap menghasilkan status keluar 128+[<signal number>. Misalnya, terminasi oleh SIGINT( sinyal 2 ) menghasilkan status keluar 130.

Catatan

  1. Beberapa jawaban mendefinisikan status keluar 2 sebagai "Penyalahgunaan bash builtins". Ini hanya berlaku ketika bash (atau skrip bash) keluar dengan status 2. Anggap saja ini kasus khusus kesalahan penggunaan yang salah.

  2. Dalam sysexits.h, yang disebutkan dalam jawaban paling populer , status keluar EX_USAGE("kesalahan penggunaan baris perintah") didefinisikan sebagai 64. Tetapi ini tidak mencerminkan kenyataan: Saya tidak mengetahui adanya utilitas Unix umum yang mengembalikan 64 pada permintaan yang salah (contoh selamat datang ). Pembacaan yang hati-hati terhadap kode sumber mengungkapkan bahwa sysexits.hitu aspirasional, dan bukan cerminan dari penggunaan yang sebenarnya:

     *    This include file attempts to categorize possible error
     *    exit statuses for system programs, notably delivermail
     *    and the Berkeley network.
    
     *    Error numbers begin at EX__BASE [64] to reduce the possibility of 
     *    clashing with oth­er exit statuses that random programs may 
     *    already return. 
    

    Dengan kata lain, definisi-definisi ini tidak mencerminkan praktik umum pada waktu itu (1993) tetapi sengaja tidak sesuai dengan itu. Sayang sekali.

Alexis
sumber
Apa yang harus program kembali ketika itu tidak menangani pemutusan dengan menangkap SIGINT / Ctrl-C? Masih 130? Apakah menggunakan shell lain selain masalah bash?
Gringo Suave
1
Shell yang menjalankan program tidak relevan; suatu proses secara teori dapat memilih untuk keluar dengan status berbeda tergantung pada proses induknya, tetapi saya belum pernah mendengar kasus di mana ini terjadi.
alexis
1
Jika suatu program menangkap SIGINT, membersihkan, dan keluar, statusnya adalah apa pun yang masuk akal untuk program tersebut. Misalnya, moreakan mengatur ulang mode terminal dan keluar dengan status 0 (Anda dapat mencobanya).
alexis
1
Jawaban ini menyiratkan tingkat standardisasi yang jauh lebih tinggi daripada apa yang sebenarnya terjadi. Tidak ada standardisasi yang tepat dari arti nilai 2, dan praktik aktual kemudian diprediksi sangat campuran. Memang benar bahwa banyak alat mengembalikan 2 untuk penggunaan yang tidak benar, tetapi itu tidak sepenuhnya didefinisikan dengan baik apa yang dimaksud dengan "penggunaan yang tidak benar", dan banyak lainnya tidak mematuhi konvensi ini.
tripleee
@tripleee "tools" juga tidak didefinisikan dengan baik! :-) Tentu, siapa pun dapat menulis program baris perintah dan dapat mengembalikan apa saja, tetapi "Utilitas baris perintah Unix" lama yang sudah ada lebih lama dari Linux, atau isi dari GNU coreutils, cukup konsisten dalam hal ini. Jika Anda berpikir sebaliknya, sebutkan beberapa alat dalam grup ini yang tidak menggunakan status 2 dengan cara ini. Juga, "penggunaan yang tidak benar" adalah istilah Anda (dan saya setuju itu istilah yang tidak jelas); Saya menulis "kesalahan penggunaan perintah baris", yang cukup spesifik: opsi yang tidak ada atau tidak kompatibel, jumlah argumen non-opsi yang salah, dll.
alexis
25

Tidak ada kode keluar standar, selain 0 artinya berhasil. Non-nol tidak berarti kegagalan juga.

stdlib.h mendefinisikan EXIT_FAILUREsebagai 1 dan EXIT_SUCCESS0, tapi hanya itu saja.

11 pada segfault menarik, karena 11 adalah nomor sinyal yang digunakan kernel untuk mematikan proses jika terjadi segfault. Kemungkinan ada beberapa mekanisme, baik di kernel atau di shell, yang menerjemahkannya ke dalam kode keluar.

Chris Arguin
sumber
20

sysexits.h memiliki daftar kode keluar standar. Sepertinya tanggal kembali ke setidaknya tahun 1993 dan beberapa proyek besar seperti Postfix menggunakannya, jadi saya membayangkan itu cara untuk pergi.

Dari halaman manual OpenBSD:

Menurut style (9), bukan praktik yang baik untuk memanggil exit (3) dengan nilai-nilai default untuk menunjukkan kondisi kegagalan saat mengakhiri program. Sebagai gantinya, kode keluar yang telah ditentukan dari sysexits harus digunakan, sehingga pemanggil proses dapat memperoleh estimasi kasar tentang kelas kegagalan tanpa melihat kode sumber.

sumber
8

Untuk perkiraan pertama, 0 adalah sukses, bukan nol adalah kegagalan, dengan 1 adalah kegagalan umum, dan apa pun yang lebih besar dari satu adalah kegagalan spesifik. Selain pengecualian sepele dari pengujian salah, yang keduanya dirancang untuk memberikan 1 untuk keberhasilan, ada beberapa pengecualian lain yang saya temukan.

Lebih realistis, 0 berarti berhasil atau mungkin gagal, 1 berarti kegagalan umum atau mungkin berhasil, 2 berarti kegagalan umum jika 1 dan 0 keduanya digunakan untuk sukses, tetapi mungkin berhasil juga.

Perintah diff memberikan 0 jika file yang dibandingkan adalah identik, 1 jika mereka berbeda, dan 2 jika biner berbeda. 2 juga berarti kegagalan. Perintah less memberi 1 untuk kegagalan kecuali jika Anda gagal memberikan argumen, dalam hal ini, ia keluar 0 meskipun gagal.

Perintah lebih banyak dan perintah ejaan memberikan 1 untuk kegagalan, kecuali kegagalan itu adalah hasil dari izin yang ditolak, file tidak ada, atau upaya untuk membaca direktori. Dalam semua kasus ini, mereka keluar 0 meskipun gagal.

Kemudian perintah expr memberikan 1 untuk sucess kecuali outputnya adalah string kosong atau nol, dalam hal ini, 0 adalah sucess. 2 dan 3 adalah kegagalan.

Lalu ada kasus di mana keberhasilan atau kegagalan bersifat ambigu. Ketika grep gagal menemukan pola, ia keluar 1, tetapi keluar 2 untuk kegagalan asli (seperti izin ditolak). Klist juga keluar 1 ketika gagal menemukan tiket, meskipun ini sebenarnya bukan kegagalan daripada ketika grep tidak menemukan pola, atau ketika Anda ls direktori kosong.

Jadi, sayangnya, kekuatan unix yang tampaknya tidak memberlakukan seperangkat aturan logis, bahkan pada executable yang sangat umum digunakan.

Frederick
sumber
Saya akan menunjukkan perilaku diff juga. wget juga memiliki kesalahan terperinci (mis. 6 untuk kegagalan otentikasi), tetapi kemudian mereka menggunakan 1 = kesalahan umum, 2..n = kesalahan spesifik
PypeBros
5

Program mengembalikan kode keluar 16 bit. Jika program dimatikan dengan sinyal maka byte orde tinggi berisi sinyal yang digunakan, sebaliknya byte orde rendah adalah status keluar yang dikembalikan oleh programmer.

Bagaimana kode keluar itu ditetapkan ke variabel status $? kemudian terserah shell. Bash menyimpan 7 bit status yang lebih rendah dan kemudian menggunakan 128 + (sinyal nr) untuk menunjukkan sinyal.

Satu-satunya konvensi "standar" untuk program adalah 0 untuk kesuksesan, bukan nol untuk kesalahan. Konvensi lain yang digunakan adalah untuk mengembalikan errno pada kesalahan.

Dean Povey
sumber
3

Kode keluar Unix standar didefinisikan oleh sysexits.h, seperti poster lain yang disebutkan. Kode keluar yang sama digunakan oleh perpustakaan portabel seperti Poco - berikut adalah daftarnya:

http://pocoproject.org/docs/Poco.Util.Application.html#16218

Sinyal 11 adalah sinyal SIGSEGV (pelanggaran segmen), yang berbeda dari kode pengembalian. Sinyal ini dihasilkan oleh kernel sebagai tanggapan terhadap akses halaman yang buruk, yang menyebabkan program berhenti. Daftar sinyal dapat ditemukan di halaman manual sinyal (jalankan "sinyal manusia").

Daniel Schuler
sumber
1

Ketika Linux mengembalikan 0, itu berarti sukses. Apa pun artinya kegagalan, setiap program memiliki kode keluar sendiri, jadi cukup lama untuk mendaftar semuanya ...!

Tentang kode kesalahan 11, itu memang nomor kesalahan segmentasi, sebagian besar berarti bahwa program mengakses lokasi memori yang tidak ditetapkan.

Amadeus45
sumber
1
Itu selalu 11 karena kernel membunuhnya dan memberikan "nilai keluar." Demikian juga, jenis kesalahan lainnya akan selalu mendapatkan nilai keluar yang sama.
Alex Gartrell