Linux'ta standart çıkış durumu kodları var mı?


308

Bir işlemin çıkış durumu 0 ise Linux'ta doğru şekilde tamamlandığı kabul edilir.

Segmentasyon hatalarının genellikle 11 çıkış durumu ile sonuçlandığını gördüm, ancak bunun basitçe çalıştığım kongre olup olmadığını (hepsi başarısız olan uygulamalar) veya standart olup olmadığını bilmiyorum.

Linux'taki işlemler için standart çıkış kodları var mı?


6
Sistem işlevleri tarafından döndürülen "sistem hata numarası" adlı bir şey arıyorsanız, burada errno
marinara bakın

Yanıtlar:


86

Dönüş kodunun 8 biti ve öldürme sinyalinin sayısının 8 biti wait(2)& co'dan dönüşte tek bir değerde karıştırılır . .

#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" */
}

Çıkış durumunu nasıl belirliyorsunuz? Geleneksel olarak, kabuk yalnızca 8 bitlik bir dönüş kodu depolar, ancak işlem anormal olarak sonlandırıldıysa yüksek biti ayarlar.

$ sh -c 'çıkış 42'; echo $?
42
$ sh -c 'öldür -SEGV $$'; echo $?
Segmentasyon hatası
139
139 - 128 dolar
11

Bundan başka bir şey görüyorsanız, programın muhtemelen normal olarak SIGSEGVçağıran bir sinyal işleyicisi vardır exit, bu yüzden aslında sinyal tarafından öldürülmez. (Programlar SIGKILLve dışındaki herhangi bir sinyali kullanmayı seçebilir SIGSTOP.)


8
Sorunun şimdi nasıl göründüğü göz önüne alındığında, bu en yararlı (ve böylece kabul edilmiş) cevap gibi görünmemektedir.
David J.

332

Bölüm 1: Gelişmiş Bash Komut Dosyası Kılavuzu

Her zaman olduğu gibi, Gelişmiş Bash Scripting Guide sahiptir büyük bilgi : (. Bu ancak bir kanonik olmayan bir URL'ye başka cevap bağlantılı olduğunu)

1: Genel hatalar için catchall
2: Kabuk yerleşiklerinin yanlış kullanımı (Bash belgelerine göre)
126 : Çağrılan komut yürütülemiyor
127: "komut bulunamadı"
128:
128 + n'den çıkmak için geçersiz argüman "n" Önemli hata sinyali "n"
255: Çıkış durum aralık dışında (çıkış yalnızca 0 - 255 aralığında tamsayı değişkenlerini alır)

Bölüm 2: Sysexits.h

ABSG referansları sysexits.h.

Linux'ta:

$ 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 */

5
Unix'in bazı tatlarında, bazı komutların diğer şeyleri belirtmek için 2 çıkış durumu kullandığını unutmayın. Örneğin, birçok grep uygulaması bir hatayı belirtmek için 2 çıkış durumunu kullanır ve seçilen satır bulunamadığını ifade etmek için 1 çıkış durumunu kullanır.
NamshubWriter

3
BSD'ler üzerinde sysexits.h gelen bilgileri özetleyen bir adam sayfası var:man sysexits
georgebrock

6
@NamshubWriter ne dedi. Çıkış durumu 2 , yalnızca "bazı unix tatları" nda değil, genel olarak Unix yardımcı programlarında yanlış komut satırı kullanımı için evrensel bir çözümdür. Bu cevapta gösterilen başlık, şimdi veya 1987'de yazıldığı zaman gerçek sözleşmeleri yansıtmıyor.
alexis

ABS "harika" değil. Lütfen konuyu okuyun; eleştiri bulmak tam olarak zor değil.
Üçlü

Peki gerçek resmi kaynak kodu nerede sysexits.h? Adam sayfa herkes referans sadece düz yazı türüdür tutar. Örneğin EX_OK, diğer kodlar gibi normatif bir şekilde referansta bulunur ancak tanımlamaz. Daha eksik olan var mı?
Garret Wilson

71

'1' >>> Genel hatalar için catchall

'2' >>> Mermi yapılarının yanlış kullanımı (Bash belgelerine göre)

'126' >>> Çağrılan komut çalıştırılamıyor

'127' >>> "komut bulunamadı"

'128' >>> Çıkmak için geçersiz argüman

'128 + n' >>> Önemli hata sinyali "n"

'130' >>> Control-C tarafından sonlandırılan komut dosyası

'255' >>> Çıkış durumu aralık dışında

Bu bash için. Ancak, diğer uygulamalar için farklı çıkış kodları vardır.


1
İkiniz de aynı anda cevap verdiniz. Tian bağlantılarınızı görmek ve onları yapıştırmak için oldukça hızlı olmalı.
Nathan Fellman

6
'Kontrol-C verimi 130'un sinyal n için' 128 + n 'ile tutarlı olduğunu unutmayın; control-C, sinyal 2 olan SIGINT üretir.
Jonathan Leffler

3
Bu, Atıf olmadan ABS'den intihal gibi görünüyor. (ABS'nin yanlış veya en azından yanıltıcı bilgi içerdiğinden söyleyebiliriz.)
üçlü

4
Bunlar Gelişmiş Bash-Komut Dosyası Kılavuzu'na göre SAKLIDIR çıkış kodlarıdır . Bu , kullanıcı tanımlı çıkış parametreleri için bu değerlerden kaçınılması gerektiği anlamına gelir .
ingyhere

53

Eski yanıtların hiçbiri çıkış durumu 2'yi doğru olarak tanımlamaz. İddia ettiklerinin aksine, durum 2, komut satırı yardımcı programlarınızın yanlış çağrıldığında gerçekte döndüğü durumdur. (Evet, bir cevap dokuz yaşında olabilir, yüzlerce yukarı oy alabilir ve yine de yanlış olabilir.)

İşte normal sonlandırma için gerçek, uzun süredir devam eden çıkış durumu kuralı, yani sinyalle değil:

  • Çıkış durumu 0: başarı
  • Durum 1'den çık: Program tarafından tanımlandığı şekliyle "hata"
  • Çıkış durumu 2: komut satırı kullanım hatası

Örneğin, diffkarşılaştırdığı dosyalar aynı ise 0, farklıysa 1 döndürür. Uzun süredir devam eden kurallara göre, unix programları yanlış çağrıldıklarında çıkış durumu 2'yi döndürür (bilinmeyen seçenekler, yanlış sayıda argüman vb.) Örneğin diff -N, grep -Yya diff a b cda hepsi $?2 olarak ayarlanacaktır. 1970'lerde Unix'in ilk günleri.

Kabul edilen cevap , bir komut bir sinyal tarafından sonlandırıldığında ne olacağını açıklar . Kısaca, yakalanmamış bir sinyale bağlı olarak sonlandırma çıkış durumuna neden olur 128+[<signal number>. Örneğin, SIGINT( sinyal 2 ) ile sonlandırma çıkış durumu 130 ile sonuçlanır.

notlar

  1. Bazı yanıtlar çıkış durumu 2'yi "Bash yerleşimlerinin yanlış kullanımı" olarak tanımlar. Bu yalnızca bash (veya bash betiği) durum 2 ile çıktığında geçerlidir. Özel bir yanlış kullanım hatası durumu olduğunu düşünün.

  2. Olarak sysexits.h, bahsedilen en popüler cevap , çıkış durumu EX_USAGEdeğil gerçeği yansıtır ( "komut satırı kullanım hatası") 64. olarak tanımlanır Ama bunu yapar: Ben farkında değilim herhangi yanlış çağırma döner 64 (örnekler hoşgeldin ortak Unix özelliği ). Dikkatli okunduğu kaynak kodu ortaya koymaktadır sysexits.hziyade gerçek bir kullanım yansımasından çok, aspirational:

     *    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. 
    

    Başka bir deyişle, bu tanımlar o zamanlar (1993) ortak uygulamayı yansıtmaz, ama kasıtlı olarak onunla uyumsuzdur. Yazık daha fazla.


Ne gerekir bunun bir program dönüş yapar SIGINT / Ctrl-C yakalayarak sap sonlandırılmasını? Hala 130 mu? Bash dışında başka bir mermi kullanmak mı?
Gringo Suave

1
Programı yürüten kabuk önemsizdir; Bir süreç teorik olarak ana sürecine bağlı olarak farklı durumlarla çıkmayı seçebilir, ancak bunun gerçekleştiği bir durumu daha önce hiç duymadım.
alexis

1
Bir program SIGINT'i yakalar, temizler ve yine de çıkarsa, durum program için anlamlı olan şeydir. Örneğin more, terminal modlarını sıfırlar ve 0 durumuyla çıkar (deneyebilirsiniz).
alexis

1
Bu cevap, gerçekte olandan çok daha yüksek bir standardizasyon derecesi anlamına gelir. 2 değerinin anlamının uygun bir standardizasyonu yoktur ve gerçek uygulama tahmin edilebilir şekilde çok karışıktır. Birçok aracın uygunsuz kullanım için 2 döndürdüğü doğrudur, ancak "yanlış kullanım" ın ne anlama geldiği tam olarak tanımlanmamıştır ve diğerleri de bu sözleşmeye uymaz.
Üçlü

@tripleee "araçlar" da iyi tanımlanmış değil! :-) Elbette, herkes bir komut satırı programı yazabilir ve herhangi bir şey döndürebilir, ancak Linux'tan daha uzun olan eski okul "Unix komut satırı yardımcı programları" veya GNU coreutils içeriği oldukça bu konuda tutarlı. Aksini düşünüyorsanız, lütfen bu grupta durum 2'yi bu şekilde kullanmayan bazı araçları adlandırın. Ayrıca, "uygunsuz kullanım" teriminizdir (ve bunun belirsiz bir terim olduğunu kabul ediyorum); Oldukça spesifik olan "komut satırı kullanım hatası" yazdım: var olmayan veya uyumsuz seçenekler, seçenek olmayan argümanların yanlış sayısı, vb.
alexis

25

Başarı anlamına gelen 0 dışında standart çıkış kodu yoktur. Sıfırdan farklı olmak da başarısızlık demek değildir.

stdlib.h, EXIT_FAILURE1 ve EXIT_SUCCESS0 olarak tanımlar , ancak bununla ilgilidir.

Segfault üzerindeki 11 ilginçtir, çünkü 11 çekirdeğin bir segfault durumunda işlemi öldürmek için kullandığı sinyal numarasıdır. Çekirdekte veya kabukta, bunu çıkış koduna çeviren bazı mekanizmalar vardır.


20

sysexits.h standart çıkış kodlarının bir listesine sahiptir. En azından 1993'e kadar uzanıyor gibi görünüyor ve Postfix gibi bazı büyük projeler bunu kullanıyor, bu yüzden bunun yolunun olduğunu hayal ediyorum.

OpenBSD kılavuz sayfasından:

Stile (9) göre, bir programı sonlandırırken bir başarısızlık durumunu belirtmek için çıkışa (3) rastgele değerlerle çağrı yapmak iyi bir uygulama değildir. Bunun yerine, sysexits'ten önceden tanımlanmış çıkış kodları kullanılmalıdır, böylece sürecin arayanı kaynak koduna bakmadan başarısızlık sınıfı hakkında kabaca bir tahmin alabilir.

8

İlk yaklaşıma göre, 0 başarılı, sıfır olmayan bir başarısızlık, 1 genel bir başarısızlık ve birden büyük bir şey belirli bir başarısızlıktır. Her ikisi de başarı için 1 vermek üzere tasarlanan önemsiz yanlış ve test istisnalarının yanı sıra, bulduğum birkaç istisna daha var.

Daha gerçekçi olarak, 0 başarı veya belki başarısızlık anlamına gelir, 1 genel başarısızlık veya belki başarı anlamına gelir, 2 hem 1 hem de 0 başarı için kullanılıyorsa, ama belki de başarı anlamına gelir.

Diff komutu, karşılaştırılan dosyalar aynı ise 0, farklıysa 1 ve ikili dosyalar farklıysa 2 verir. 2 aynı zamanda başarısızlık demektir. Daha az komut, bağımsız değişken sağlamadığınız sürece hata için 1 verir; bu durumda, başarısız olmasına rağmen 0'dan çıkar.

Daha fazla komut ve yazım komutu, hata izin verilmedi, var olmayan bir dosya veya bir dizini okuma girişiminden kaynaklanmadığı sürece hata için 1 verir. Bu vakaların herhangi birinde, başarısız olmasına rağmen 0'dan çıkarlar.

Daha sonra expr komutu, çıktı boş dize veya sıfır olmadığı sürece başarı için 1 verir; bu durumda 0 başarıdır. 2 ve 3 başarısızdır.

Sonra başarı veya başarısızlığın belirsiz olduğu durumlar vardır. Grep bir desen bulamadığında, 1'den çıkar, ancak gerçek bir hata için 2'den çıkar (izin reddedildi gibi). Klist, bir bilet bulamadığında da 1'den çıkar; ancak bu, grep'in bir desen bulamamasından veya boş bir dizin olduğunuzdan daha fazla başarısızlık olmamasına rağmen.

Ne yazık ki, unix güçleri, çok yaygın olarak kullanılan yürütülebilir dosyalarda bile, herhangi bir mantıksal kurallar dizisini zorlamıyor gibi görünmektedir.


Diff'in davranışını da belirtmek üzereydim. wget ayrıca ayrıntılı hatalara sahiptir (örneğin kimlik doğrulama hatası için 6), ancak daha sonra 1 = genel hata, 2..n = belirli bir hata kullanırlar
PypeBros

5

Programlar 16 bitlik çıkış kodu döndürür. Program bir sinyal ile öldürülmüşse, yüksek dereceli bayt kullanılan sinyali içerir, aksi takdirde düşük dereceli bayt programcı tarafından döndürülen çıkış durumudur.

Bu çıkış kodu $ durum değişkenine nasıl atanır? sonra kabuğa kadar. Bash, durumun alt 7 bitini tutar ve daha sonra bir sinyali göstermek için 128 + (sinyal no) kullanır.

Programlar için tek "standart" kural, başarı için 0, hata için sıfır değildir. Kullanılan başka bir kural, hata durumunda errno döndürmektir.


3

Standart Unix çıkış kodları sysexits.h tarafından belirtilen başka bir poster olarak tanımlanır. Aynı çıkış kodları Poco gibi taşınabilir kütüphaneler tarafından kullanılır - işte bunların listesi:

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

Bir sinyal 11, bir dönüş kodundan farklı bir SIGSEGV (segment ihlali) sinyalidir. Bu sinyal, kötü bir sayfa erişimine yanıt olarak çekirdek tarafından oluşturulur ve bu da programın sonlandırılmasına neden olur. Sinyal listesi sayfasında sinyal listesi bulunabilir ("man sinyali" çalıştırın).


1

Linux 0 döndürdüğünde, başarı demektir. Başka bir şey başarısızlık demektir, her programın kendi çıkış kodları vardır, bu yüzden hepsini listelemek oldukça uzun olurdu ...!

11 hata kodu hakkında, segmentasyon hata numarası, çoğunlukla programın atanmamış bir bellek konumuna eriştiği anlamına gelir.


1
Her zaman 11 olur çünkü çekirdek onu öldürür ve "çıkış değerini" atar. Benzer şekilde, diğer Arıza türleri her zaman aynı çıkış değerini alacaktır.
Alex Gartrell
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.