Linux'ta çıkış kodlarının minimum ve maksimum değerleri nedir?


40

Linux'ta aşağıdaki çıkış kodlarının minimum ve maksimum değerleri nedir:

  1. Çıkış kodu ikili bir çalıştırılabilir dosyadan döndürüldü (örneğin: bir C programı).
  2. Çıkış kodu bash betiğinden döndürülür (çağrılırken exit).
  3. Çıkış kodu bir fonksiyondan döndürülür (çağrılırken return). Bunun 0ve arasında olduğunu düşünüyorum 255.

Bölüm 3 için, bir kabuk işlevinden geri dönmek mi istiyorsunuz ? Bu kabuk bağlı olabilir, ama ben Bash kılavuzu diyor "olduğuna dikkat Çık durumları arasında kalan 0 ile 255 ve" " de bu aralıkla sınırlıdır kabuk yerleşikleri ve bileşik komutları çıkın durumları. " return, Elbette, bir kabuk yerleşiği.
Toby Speight

İlgili (sorularınızın çoğuna cevaplar vardır): İşlem sonlandırıldığında varsayılan çıkış kodu?
Stéphane Chazelas,

@TobySpeight, bashkabuğun bir kısıtlamasıdır . Gibi bazı diğer kabuklar, bunun gibi zshimzalı herhangi bir 32 bitlik değeri geri döndürebilir exit. Bazıları , destekledikleri herhangi bir türün verilerini geri alabilir rcveya esgeri verebilir (skalar veya liste). Detaylar için bağlantılı soru-cevap bölümüne bakınız.
Stéphane Chazelas,

Yanıtlar:


74

_exit()/ exit_group()System çağrısına geçen sayı (bazen çıkış kodunun veya sinyal numarasının kodlanmasına da atıfta bulunan çıkış durumuyla belirsizliği önlemek için çıkış kodu olarak da adlandırılır ve işlemin normal şekilde öldürülüp ölülmediğine bağlı olarak ek bilgi) ), Linux gibi Unix benzeri sistemlerde, genellikle -2147483648 (-2 31 ) ila 2147483647 (2 31 -1) değerlerine sahip bir 32bit tam sayıdır .int

Üst süreç (veya çocuk subreaper ya Ancak, tüm sistemlerde, initebeveyn ölmüşse) kullanan wait(), waitpid(), wait3(), wait4()sistem çağrıları sadece bunun alt 8 bit 0 255 (2 kullanılabilir (değerlerdir, geri almak için 8 - 1)).

Kullanırken waitid()API (veya SIGCHLD üzerinde bir sinyal işleyicisi), en çok sistemlerde (ve POSIX artık daha net bir standart 2016 baskısında gerektirir (bakınız _exit()özellikleri içinde (tam sayı kullanılabilir,)) si_statusgeri yapısının alanındaki ). Yine de Linux'ta durum böyle değil waitid(), ancak gelecekte de değişmesi muhtemel olsa da, API ile sayıyı 8 bit olarak kısaltır .

Genellikle, yalnızca 0 (genellikle başarı anlamına gelir) değerlerini yalnızca 125 olarak kullanmak istersiniz; zira birçok kabuk , öldürülen bir sürecin sinyal numarasını kodlamak için çıkış durumunu$? temsil eden 128 ve özel olarak 126 ve 127 koşullar.

exit()Kabuklar için yaptığınızla aynı şeyi ifade etmek için 126 - 255 kullanmak isteyebilirsiniz $?(bir komut dosyası olduğu gibi ret=$?; ...; exit "$ret"). 0 -> 255 dışındaki değerleri kullanmak genellikle yararlı değildir. Bunu yalnızca üst öğenin waitid()kesilmeyen sistemlerde API'yi kullanacağını ve 32bit değer aralığına ihtiyaç duyduğunuzu bilmeniz durumunda yaparsınız. Eğer bir yaparsanız o Not exit(2048)Örneğin, bu geleneksel kullanarak ebeveynleri tarafından başarı olarak görülecektir wait*()API'leri.

Daha fazla bilgi için:

Sorular ve Cevaplar, diğer sorularınızın çoğuna cevap vermeli ve çıkış durumunun ne anlama geldiğini netleştirmelidir . Birkaç şey daha ekleyeceğim:

Bir süreç öldürülmedikçe veya _exit()/ exit_group()sistem çağrılarını çağırmadıkça sona erdirilemez . Eğer gelen döndüğünüzde main()de Cdönüş değeri ile, libc çağrılar bu sistem çağrısı.

Çoğu dil, exit()bu sistem çağrısını tamamlayan bir fonksiyona sahiptir ve varsa genel olarak sistem çağrısına aktarıldığı takdirde aldıkları değerdir. (C’nin exit()stdio tamponlarını temizleyen fonksiyonunun yaptığı temizlik gibi genel olarak daha fazla iş yaptığını unutmayın , atexit()kancaları çalıştırır …)

En azından şu durumda:

$ strace -e exit_group awk 'BEGIN{exit(1234)}'
exit_group(1234)                        = ?
$ strace -e exit_group mawk 'BEGIN{exit(1234)}'
exit_group(1234)                        = ?
$ strace -e exit_group busybox awk 'BEGIN{exit(1234)}'
exit_group(1234)                        = ?
$ echo | strace -e exit_group sed 'Q1234'
exit_group(1234)                        = ?
$ strace -e exit_group perl -e 'exit(1234)'
exit_group(1234)                        = ?
$ strace -e exit_group python -c 'exit(1234)'
exit_group(1234)                        = ?
$ strace -e exit_group expect -c 'exit 1234'
exit_group(1234)                        = ?
$ strace -e exit_group php -r 'exit(1234);'
exit_group(1234)                        = ?
$ strace -e exit_group zsh -c 'exit 1234'
exit_group(1234)

Zaman zaman 0-255 dışında bir değer kullandığınızda şikayetçi olanları görürsünüz:

$ echo 'm4exit(1234)' | strace -e exit_group m4
m4:stdin:1: exit status out of range: `1234'
exit_group(1)                           = ?

Negatif bir değer kullandığınızda bazı mermiler şikayet eder:

$ strace -e exit_group dash -c 'exit -1234'
dash: 1: exit: Illegal number: -1234
exit_group(2)                           = ?
$ strace -e exit_group yash -c 'exit -- -1234'
exit: `-1234' is not a valid integer
exit_group(2)                           = ?

exitÖzel yerleşik yapıya iletilen değer 0-255 dışındaysa POSIX davranışı tanımsız bırakır .

Bazı mermiler şu durumlarda bazı beklenmeyen davranışlar gösterir:

  • bash(ve mkshancak pdkshbu üzerine dayanır) 8 bit değeri kesecek şekilde kendi üzerine alır:

    $ strace -e exit_group bash -c 'exit 1234'
    exit_group(210)                         = ?
    

    Dolayısıyla, bu kabuklarda, 0-255 dışında bir değerle çıkmak istiyorsanız, aşağıdaki gibi bir şey yapmanız gerekir:

    exec zsh -c 'exit -- -12345'
    exec perl -e 'exit(-12345)'
    

    Aynı süreçte başka komutu çalıştırmak olduğunu edebilir , istediğiniz değere sahip sistem çağrısı diyoruz.

  • Diğer soru- ksh93cevaplarda belirtildiği gibi, 257 - 256 + max_signal_number çıkış değerleri için en garip davranışa sahiptir; burada çağrı yapmak yerine, exit_group()kendisini karşılık gelen sinyal ile¹ öldürür.

    $ ksh -c 'exit "$((256 + $(kill -l STOP)))"'
    zsh: suspended (signal)  ksh -c 'exit "$((256 + $(kill -l STOP)))"'
    

    ve aksi halde bash/ gibi sayıları keser mksh.


Though Bir sonraki sürümde olsa değişmesi muhtemel. Şimdi ksh93AT&T dışında bir topluluk çalışması olarak ele alındığına göre, bu davranış, bir şekilde POSIX tarafından teşvik edilmesine rağmen, geri çevriliyor.


2
Tüm çıkış kodunu si_statusLinux için uygulamak konusunda herhangi bir tartışma olup olmadığını biliyor musunuz ?
Ruslan


1
msgstr "int türünde, yani bir 32 bit tam sayı". Linux gerçekten bir int'in her zaman 32bit olacağını garanti ediyor? Bu küçük mikrodenetleyicilerden bazılarında çalışırken bile mi? Bu beni gerçekten garip hissettiriyor. POSIX kesinlikle değil.
Voo

@Voo, bu küçük mikro denetleyiciler Linux çalıştıramazlar. C inten az 16 bit olmakla birlikte , POSIX az ya da çok olmak üzere en az 32 bit ve programlama ortamları olmasını gerektirir32_t . Linux, bitlerin 32 bit dışında bir programlama ortamını destekleyip desteklemediğini bilmiyorum, hiç karşılaşmadım.
Stéphane Chazelas,

1
POSIX uyumlu bir işletim sisteminde, Bourne Kabuğunun son sürümündeki tam 32 bit çıkış kodunu alabilirsiniz, bakınız: schillix.sourceforge.net/man/man1/bosh.1.html
schily

12

Asgari 0, ve bu başarı değeri olarak kabul edilir. Diğerleri başarısız. Maksimum olarak 255da bilinir -1.

Bu kurallar hem betikler hem de diğer çalıştırılabilirler ve ayrıca kabuk işlevleri için geçerlidir.

Daha büyük değerler modulo 256 ile sonuçlanır.


2
İçerisinde, kesin olmak gerekirse, bazı Bourne gibi kabuklar (fakat bashdiğer en sık kullanılan) geçirilen çıkış kodu exityerleşiği olan olmayan modülo-256 muamelesi, ve bunun yerine bir hataya neden olur. (Örneğin, genel exit -1olarak exit 255çoğu mermide taşınabilir bir eşdeğer değildir ). Ve exit(-1)C düzeyinde eşdeğer olup olmadığının exit(255)kesin olarak çalışması kesin olan bir detaydır, ancak uygulamanın tanımlanmış davranışına dayanır (bu uygulamada kullanmanız muhtemel modern sistemlerde bir sorun olmasa da).
mtraceur

Bildiğim kadarıyla, sadece ksh93 exit(1)parametresini 8 bit ile sınırlandırıyor .
schily

6

Bu çok basit görünüyor, ama ah, hadi.

C dili (ve diğer birçok dilin doğrudan ya da dolaylı olarak izlenmesi) , geri dönüş değeri ile aynı argümanla mainçağrılmaya eşit olmasını gerektirir exit. Bu bir tamsayıdır (dönüş tipi çok açık olduğu int), yani prensip olarak aralık olacaktır INT_MINiçin INT_MAX.

Bununla birlikte, POSIX , yalnızca geçirilen en düşük 8 bitin exit, tam anlamıyla "status & 0xFF" gibi, bekleyen bir üst işlem için kullanılabilir olacağını belirtir .
Bu yüzden pratikte, çıkış kodu yalnızca en düşük 8 bitin ayarlandığı (hala imzalanmış) bir tamsayıdır.

Böylece minimum -128 ve maksimum 127 olacaktır . Dayan, bu doğru değil. 0 ile 255 arasında olacak.

Ama ne yazık ki, elbette bu kadar basit olamaz . Uygulamada, Linux (ya da bash) farklı yapar . Geçerli dönüş kodu aralığı 0 ila 255'tir (yani imzasız).

Karışıklığın önlenmesi konusunda güvenli tarafta olmak, dönüş kodlarının imzasız olduğunu varsaymak ve geri döndüğünüz her şeyi imzasız hale getirmek iyi bir fikir olabilir wait. Bu şekilde bir kabukta gördüğünüz şeyle tutarlıdır. En üstteki bitler (en önemlisi de dahil olmak üzere) silindiğinden, teknik olarak imzalanmış olmasına rağmen, gerçek değerler daima işaretsizdir (işaret biti asla ayarlanmadığından).
Ayrıca, bir çıkış kodunu karşılaştırmayla ilgili genel hatadan kaçınılmasına da yardımcı olur -1; bu , bazı nedenlerden dolayı , bir program çıktığında bile görünmeyecek gibi görünmez -1(nedenini tahmin et!).

Son noktanız hakkında, bir işlevden dönen, eğer bu işlev gerçekleşirse mainyukarı bakın. Aksi halde, fonksiyonun geri dönüş tipinin ne olduğuna bağlı olarak prensipte her şey olabilir (dahil void).


1989'dan önce waitid()tanıtıldığın zaman haklıydın .
schily

@schily: Ne demek istediğinden emin değil misin? waitid()sadece aynı şeyi yapar, biraz farklı. Belli bir kimliği veya herhangi bir iş parçacığı bekler ve sivri-to sonuçları yazar siginfo_tyapısı si_statusolan int(yani ... imzalı , sadece aynı). Yine de, exit()sadece en alttaki 8 bitin üzerinden geçer, bu yüzden ... kesinlikle başlık altındaki aynı şey.
Damon,

exit()parametrenin tüm 32 bitini çekirdeğe geçirir ve waitid()32 bitin tümünü çıkış kodundan döndürür. Belki de Linux'ta kimsenin hataları gidermeyi umursamadığı yerleri kontrol ettin. Bana inanmıyorsan, POSIX uyumlu bir işletim sisteminde kontrol et ...
schily

@schily: Eğer bu doğruysa (bunun olduğunu sanmıyorum ama yine de), o zaman Linux bozuldu . Lütfen "En azından" ifadesininexit altındaki ikinci satırın "-" ile bağlantılı olan POSIX özelliğini belirtin: " . Uygun bir uygulama böyle çalışır - en düşük 8 bit, 32 değil. 32 bit geçirilen bir referansınız var mı?
Damon,

Linux'un bozulduğundan bahsetmiştim. Daha da kötüsü: Linux çekirdeği insanları hataları düzeltmeyi reddediyor. POSIX standardını okursanız, 1995 versiyonunun (SUSv1) orijinal olarak 1989 yılında SVr4 tarafından sunulan özelliği doğru şekilde açıkladığını ve standardın son sürümlerinin (örn. SUSv7tc2) açıkça belirtildiği waitid()ve siginfo_tbunun SIGCHLDişleyicinin geri dönüşüne geçtiğini göreceksiniz. exit()parametreden tüm 32 bit .
schily

2
  1. Çıkış kodu ikili bir çalıştırılabilir dosyadan döndürüldü (örneğin: bir C programı).
  2. Çıkış kodu bash betiğinden döndürüldü (çıkış çağırırken).

Herhangi bir işlemden kodlardan çıkın - ikili bir çalıştırılabilir dosya, bir kabuk betiği veya başka herhangi bir şey - 0 - 255 arasındadır. Bu değere daha büyük bir değer iletmek mümkündür exit(), ancak durumun yalnızca 8 bitine erişebilir diğer süreçler aracılığıyla wait().

  1. Çıkış kodu bir fonksiyondan geri döndü (dönüş çağırırken). Bunun 0 ile 255 arasında olduğunu düşünüyorum.

AC fonksiyonu hemen hemen her tipe geri döndürülebilir. Dönüş değeri sınırları, bu tür tamamen belirlenir: örneğin, -128 bir fonksiyon için 127 dönen signed charya da 0 fonksiyonu geri döndürmek için milyar ila 4.2 unsigned int, ya da herhangi bir kayan nokta sayısı kadar ve dahil olmak üzere infdönen bir işlev için double. Gibi Ve bu, sayısal olmayan türleri saymıyor void *ya da struct...

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.