$ Anlamı? kabuk dolar (dolar soru işareti)


Yanıtlar:


212

Bu, son yürütülen komutun çıkış durumudur.

Örneğin, komut trueher zaman için bir durum döndürür 0ve falseher zaman bir durum döndürür 1:

true
echo $? # echoes 0
false
echo $? # echoes 1

Kılavuzdan: ( man bashkabuğunuzu arayarak erişilebilir )

$?       En son yürütülen ön plan boru hattının çıkış durumuna genişler.

Kural olarak bir çıkış durumu 0başarı anlamına gelir ve sıfır olmayan dönüş durumu başarısızlık anlamına gelir. Wikipedia'daki çıkış durumları hakkında daha fazla bilgi edinin .

Bu çevrimiçi kılavuzda görebileceğiniz gibi, bunun gibi başka özel değişkenler de vardır: https://www.gnu.org/s/bash/manual/bash.html#Special-Parameters


Not $ve ?iki ayrı parametredir ve $?bash (1) kılavuzunda görünmez.
Josh Habdas

19

$?son yürütülen komutun çıkış değerini döndürür. echo $?bu değeri konsolda yazdırır. sıfır, başarılı olmayan bir yürütme anlamına gelirken, sıfır olmayan değerler çeşitli hata nedenleriyle eşlenir.

Bu yüzden senaryo yazarken; Aşağıdaki sözdizimini kullanma eğilimindeyim

if [ $? -eq 0 ]; then
 # do something
else
 # do something else
fi

Karşılaştırma eşittir 0ya da eşit değildir 0.

** Güncelleme Yoruma dayanarak: İdeal olarak, karşılaştırma için yukarıdaki kod bloğunu kullanmamalısınız, @tripleee yorumları ve açıklamasına bakın.


15
Hayır, bu bir antipattern. Görünen her şey cmd; if [ $? -eq 0 ]; thenyeniden düzenlenmelidir if cmd; then. Çok amaçlı bir if(ve kabuğu diğer akış kontrol deyimleri) bir komutu çalıştırmak ve çıkış durumu incelemektir.
Üçlü

if cmd;çok okunabilir olmayabilir, özellikle cmd başka bir komut dosyasına atıfta bulunursa.
Saurabh Ariyan

1
Bu şimdi daha da yanlış. [ 1 ]ve [ 0 ]ikisi de doğrudur; [operatör olmadan argümanın boş olmayan bir dize olup olmadığını kontrol eder.
Üçlü

2
Yapmak üzereyim vendor/bin/drush status bootstrap | grep -q $(vendor/bin/drush php-eval 'if (function_exists("t")) echo t("Successful");') &> /dev/null;. Eğer bunu tek bir satıra koymam gerekirse, if [ ... ]çok okunaksız olurdu. Daha if [ $drupal_installed -eq 0 ]sonra söyleyebilmem için bu satırın çıktısını bir değişkene kaydetmeyi planlıyorum .
üçüncü

1
@thirdender Bunun için uygun çözüm, karmaşık testi bir kabuk işlevinde kapsüllemektir.
üçlü

12

echo $? - En son yürütülen komutun ÇIKIŞ DURUMU'nu verir . Bu ÇIKIŞ DURUMU büyük olasılıkla SIFIR ima ile bir sayı olacaktır Başarı ve herhangi OLMAYAN SIFIR değeri gösteren Başarısızlık

? - Bu bash içinde özel bir parametre / değişkendir.

, $? - "?" Değişkeninde saklanan değeri verir.

BASH'deki benzer bazı özel parametreler 1,2, *, #'dır (Normalde echo komutunda $ 1, $ 2, $ *, $ #, vb. Olarak görülür).



5

Minimum POSIX C çıkış durumu örneği

Anlamak için $?, önce POSIX tarafından tanımlanan işlem çıkış durumu kavramını anlamalısınız . Linux'ta:

  • Bir süreç exitsistem çağrısını çağırdığında, çekirdek sistem çağrısına iletilen değeri (int ) işlem bittikten sonra bile .

    Çıkış sistem çağrısı tarafından çağrılan exit()ANSI C fonksiyonu ve yapmanız dolaylı yaparken returngelen main.

  • Genellikle fork+ ile çıkış yapan alt süreç (Bash) olarak adlandırılan işlem exec, waitsistem çağrısı ile çocuğun çıkış durumunu alabilir

Bash kodunu düşünün:

$ false
$ echo $?
1

C "eşdeğeri":

false.c

#include <stdlib.h> /* exit */

int main(void) {
    exit(1);
}

bash.c

#include <unistd.h> /* execl */
#include <stdlib.h> /* fork */
#include <sys/wait.h> /* wait, WEXITSTATUS */
#include <stdio.h> /* printf */

int main(void) {
    if (fork() == 0) {
        /* Call false. */
        execl("./false", "./false", (char *)NULL);
    }
    int status;
    /* Wait for a child to finish. */
    wait(&status);
    /* Status encodes multiple fields,
     * we need WEXITSTATUS to get the exit status:
     * http://stackoverflow.com/questions/3659616/returning-exit-code-from-child
     **/
    printf("$? = %d\n", WEXITSTATUS(status));
}

Derleyin ve çalıştırın:

g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o bash bash.c
g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o false false.c
./bash

Çıktı:

$? = 1

Bash'te enter tuşuna bastığınızda, yukarıdaki gibi bir fork + exec + wait gerçekleşir ve bash daha sonra $?çatallı işlemin çıkış durumuna ayarlanır .

Not: gibi yerleşik komutlar için echobir işlemin üretilmesine gerek yoktur ve Bash $?harici bir işlemi simüle etmek için 0'a ayarlanır .

Standartlar ve belgeler

POSIX 7 2.5.2 "Özel Parametreler" http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02 :

? En son boru hattının ondalık çıkış durumuna genişler (bkz. Boru Hatları).

man bash "Özel Parametreler":

Kabuk birkaç parametreyi özel olarak ele alır. Bu parametrelere yalnızca başvurulabilir; bunlara atanmasına izin verilmez. [...]

? En son yürütülen ön plan boru hattının çıkış durumuna genişler.

ANSI C ve POSIX şunları tavsiye eder:

  • 0 programın başarılı olduğu anlamına gelir

  • diğer değerler: program bir şekilde başarısız oldu.

    Kesin değer, arızanın türünü gösterebilir.

    ANSI C herhangi bir değerin anlamını tanımlamaz ve POSIX 125'ten büyük değerleri belirtir: "POSIX" ne anlama gelir?

Bash, if

Bash'te, çıkış durumunu genellikle aşağıdaki gibi ifadeleri $?kontrol etmek için örtük ifolarak kullanırız:

if true; then
  :
fi

burada true0 döndüren bir program var.

Yukarıda belirtilenler:

true
result=$?
if [ $result = 0 ]; then
  :
fi

Ve:

if [ 1 = 1 ]; then
  :
fi

[sadece garip bir isme sahip bir programdır (ve Bash yerleşik gibi davranır) ve 1 = 1 ]argümanları, ayrıca bakınız: Bash'deki tek ve çift köşeli parantezler arasındaki fark




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.