Co robi
echo $?
znaczy w programowaniu powłoki?
Co robi
echo $?
znaczy w programowaniu powłoki?
Odpowiedzi:
To jest kod zakończenia ostatniego wykonanego polecenia.
Na przykład polecenie true
zawsze zwraca stan 0
i false
zawsze zwraca stan 1
:
true
echo $? # echoes 0
false
echo $? # echoes 1
Z instrukcji: (dostępne po wywołaniu man bash
powłoki)
$?
Rozwija się do statusu wyjścia ostatnio wykonanego potoku pierwszego planu.
Zgodnie z konwencją status wyjścia 0
oznacza sukces, a niezerowy status powrotu oznacza niepowodzenie. Dowiedz się więcej o statusach wyjścia na Wikipedii .
Istnieją inne zmienne specjalne, takie jak ta, jak widać w tym podręczniku online: https://www.gnu.org/s/bash/manual/bash.html#Special-Parameters
$
i ?
są to dwa różne parametry $?
, które nie pojawiają się na stronie podręcznika bash (1).
$?
zwraca wartość wyjściową ostatnio wykonanego polecenia. echo $?
wypisuje tę wartość na konsoli. zero oznacza pomyślne wykonanie, podczas gdy wartości niezerowe są mapowane na różne przyczyny niepowodzenia.
Dlatego podczas tworzenia skryptów; Zwykle używam następującej składni
if [ $? -eq 0 ]; then
# do something
else
# do something else
fi
Porównanie należy przeprowadzić na równych 0
lub nie równych 0
.
** Aktualizacja Na podstawie komentarza: Idealnie byłoby, gdybyś nie używał powyższego bloku kodu do porównania, zapoznaj się z komentarzami i wyjaśnieniami @tripleee.
cmd; if [ $? -eq 0 ]; then
powinno zostać zmienione if cmd; then
. Sam cel od if
(i inne instrukcje sterujące przepływem w skorupkach) jest uruchomienie komendy i zbadać jej stan wyjścia.
if cmd;
niektóre warunki mogą nie być zbyt czytelne, zwłaszcza gdy cmd odnosi się do innego skryptu.
[ 1 ]
i [ 0 ]
oba są prawdziwe; [
bez operatora sprawdza, czy argument jest niepustym łańcuchem.
vendor/bin/drush status bootstrap | grep -q $(vendor/bin/drush php-eval 'if (function_exists("t")) echo t("Successful");') &> /dev/null;
. Gdybym miał to umieścić w jednym wierszu if [ ... ]
, byłoby to strasznie nieczytelne. Planuję zapisać wynik tej linii w zmiennej, więc mogę tylko powiedzieć if [ $drupal_installed -eq 0 ]
później.
echo $? - Podaje STATUS WYJŚCIA ostatnio wykonanego polecenia . Ten STATUS WYJŚCIA najprawdopodobniej byłby liczbą z ZEREM oznaczającym sukces i jakąkolwiek wartością NIĄZ ZEROWĄ oznaczającą niepowodzenie
? - To jest jeden specjalny parametr / zmienna w bash.
$? - Podaje wartość przechowywaną w zmiennej „?”.
Niektóre podobne parametry specjalne w BASH to 1,2, *, # (zwykle widoczne w poleceniu echo jako $ 1, $ 2, $ *, $ #, itd.,).
Ma ostatni kod statusu (wartość wyjścia) polecenia.
Przykład statusu wyjścia minimalnego POSIX C.
Aby to zrozumieć $?
, musisz najpierw zrozumieć koncepcję statusu zakończenia procesu, która jest zdefiniowana w POSIX . W systemie Linux:
kiedy proces wywołuje exit
wywołanie systemowe, jądro przechowuje wartość przekazaną do wywołania systemowego (a int
) nawet po zakończeniu procesu.
Wywołanie systemowe wyjścia jest wywoływane przez funkcję exit()
ANSI C i pośrednio, gdy robisz return
from main
.
proces, który wywołał wychodzący proces potomny (Bash), często z fork
+ exec
, może pobrać status wyjścia dziecka za pomocą wait
wywołania systemowego
Rozważ kod Bash:
$ false
$ echo $?
1
„Odpowiednik” języka C to:
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));
}
Skompiluj i uruchom:
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
Wynik:
$? = 1
W Bash, kiedy wciśniesz enter, następuje fork + exec + wait, jak powyżej, a następnie bash ustawia $?
status zakończenia rozwidlonego procesu.
Uwaga: w przypadku poleceń wbudowanych, takich jak echo
proces, nie musi być spawnowany, a Bash ustawia tylko $?
0, aby symulować proces zewnętrzny.
Normy i dokumentacja
POSIX 7 2.5.2 „Parametry specjalne” http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_05_02 :
? Rozwija się do dziesiętnego statusu wyjścia najnowszego potoku (zobacz Potoki).
man bash
„Parametry specjalne”:
Powłoka traktuje specjalnie kilka parametrów. Te parametry mogą być tylko przywoływane; przypisywanie do nich nie jest dozwolone. […]
? Rozwija się do statusu wyjścia ostatnio wykonanego potoku pierwszego planu.
ANSI C i POSIX zalecają, aby:
0
oznacza, że program się powiódł
inne wartości: program w jakiś sposób zawiódł.
Dokładna wartość może wskazywać rodzaj awarii.
ANSI C nie definiuje znaczenia żadnych zmiennych, a POSIX określa wartości większe niż 125: Jakie jest znaczenie „POSIX”?
Bash używa statusu wyjścia dla if
W Bash często $?
niejawnie używamy statusu wyjścia do kontrolowania if
instrukcji, jak w:
if true; then
:
fi
gdzie true
jest programem, który po prostu zwraca 0.
Powyższe jest równoważne z:
true
result=$?
if [ $result = 0 ]; then
:
fi
I w:
if [ 1 = 1 ]; then
:
fi
[
to tylko program o dziwnej nazwie (i wbudowanym Bash, który zachowuje się tak jak on) i 1 = 1 ]
jego argumenty, zobacz także: Różnica między pojedynczymi i podwójnymi nawiasami kwadratowymi w Bash
Z http://www.gnu.org/s/bash/manual/bash.html#Special-Parameters
?
Expands to the exit status of the most recently executed foreground pipeline.
Zobacz Podręcznik Bash w 3.4.2 Parametry specjalne :
? - rozwija się do statusu wyjścia ostatnio wykonanego potoku pierwszego planu.
Jest trochę trudny do znalezienia, ponieważ nie jest wymieniony jako $?
(nazwa zmiennej to „tylko” ?
). Zobacz też , oczywiście, sekcję o statusie wyjścia ;-)
Miłego kodowania.