$? is een ingebouwde variabele die de shell (bijv. Bash) gebruikt om de exitstatuscode van de laatst uitgevoerde opdracht als een geheel getal te onthouden en die ongewijzigd blijft totdat de volgende opdracht wordt uitgevoerd.
Met behulp van deze exitstatuscode kun je het probleem dat zich tijdens het uitvoeren van de opdracht heeft voorgedaan, opsporen, wat zeer nuttig kan zijn bij het afhandelen van fouten in shellscripts.
Hieronder volgt een lijst met bekende exitstatuscodes voor bash in Linux:
| Exit status |
Beschrijving |
|---|---|
| 0 | Als er geen opdracht wordt uitgevoerd of als een opdracht succesvol wordt uitgevoerd, wordt de status op nul gezet. |
| 1 | Algemeen voorkomende fout. |
| 2 | Shell fout. |
| 126 | Uitgevoerde opdrachten kunnen niet worden uitgevoerd. |
| 127 | Opdracht niet gevonden. |
| 128 | Ongeldig argument om af te sluiten. |
| 128+n | Fatale foutmelding “n”. |
| 130 | Het script is beëindigd door Control+c. |
| 255 | De exitstatus ligt buiten het bereik. |
Standaard wordt de exitstatuscode op nul gezet wanneer je jouw systeem (of shell-sessie) start of herstart zonder opdrachten uit te voeren. De huidige exitstatuscode kan je weergeven met de volgende opdracht:
dany@pindabook:~$ echo $?
0
Zelfs als je een opdracht succesvol uitvoert, blijft de exitstatus nul.
dany@pindabook:~$ pwd
/home/dany
dany@pindabook:~$ echo $?
0
Als je een verkeerde of ongeldige optie aan een opdracht doorgeeft, wordt de exitstatuscode ingesteld op een waarde die niet nul is.
dany@pindabook:~$ cat -a bestand.txt
cat: ongeldige optie -- 'a'
Typ 'cat --help' voor meer informatie.
dany@pindabook:~$ echo $?
1
De exitstatuscode 1 geeft aan dat de laatst uitgevoerde opdracht een ongeldige optie bevatte.
Als je een verkeerd of ongeldig argument doorgeeft aan een opdracht, wordt de exitstatuscode ingesteld op 2.
dany@pindabook:~$ ls onbestaand.txt
ls: kan geen toegang krijgen tot 'onbestaand.txt': Bestand of map bestaat niet
dany@pindabook:~$ echo $?
2
Als je een verkeerde opdracht uitvoert (bijvoorbeeld met typfout), wordt de exitstatuscode ingesteld op 127.
dany@pindabook:~$ foutieveopdracht
-bash: foutieveopdracht: opdracht niet gevonden
dany@pindabook:~$ echo $?
127
Zelfs als je trefwoorden zoals true uitvoert, wordt de exitstatuscode ingesteld op 0, en voor false wordt de waarde ingesteld op 1, wat zeer effectief is bij het schrijven van een shellscript.
dany@pindabook:~$ true
dany@pindabook:~$ echo $?
0
dany@pindabook:~$ false
dany@pindabook:~$ echo $?
1
Als je één of meer opdrachten aan elkaar hebt gekoppeld, wordt in de exitstatus de waarde van de laatst uitgevoerde opdracht opgeslagen.
Voor de volgende opdrachtenreeks wordt de exitstatuscode voor de pwd opdracht weergegeven.
dany@pindabook:~$ foutieveopdracht | pwd
/home/dany
-bash: foutieveopdracht: opdracht niet gevonden
dany@pindabook:~$ echo $?
0
De exitstatuscode kan erg handig zijn bij het schrijven van shellscripts om de flow van je script met alle mogelijke fouten te verwerken. Om dit te demonstreren maken we een eenvoudig script aan met de teksteditor nano:
dany@pindabook:~$ nano script.sh
Het volgende script demonstreert het gebruik van de exitstatuscode:
#!/bin/bash
echo "Linux PindaNet tip."
status=$?
[ $status -eq 0 ] && echo "Opdracht uitgevoerd" || echo "Opdracht mislukt"
Typ dit script over en bewaar het met de sneltoets Ctrl+o gevolgd door Return. Sluit nano af met de sneltoets Ctrl+x.
Maak het script daarna uitvoerbaar en voer het uit met de volgende twee opdrachten:
dany@pindabook:~$ chmod +x script.sh
dany@pindabook:~$ ./script.sh
Linux PindaNet tip.
Opdracht uitgevoerd
Als je echter hetzelfde script wijzigt en een spelfout maakt of een verkeerde opdracht invoert, zoals hieronder weergegeven.
#!/bin/bash
echoo "Linux PindaNet tip."
status=$?
[ $status -eq 0 ] && echo "Opdracht uitgevoerd" || echo "Opdracht mislukt"
Wordt er Opdracht mislukt weergegeven in plaats van Opdracht uitgevoerd.
dany@pindabook:~$ ./script.sh
./script.sh: regel 3: echoo: opdracht niet gevonden
Opdracht mislukt
De meeste opdrachten, zoals echo of cat, volgen de standaard exitstatuscode.
De betekenis van de exitstatuscode kan echter variëren voor andere opdrachten, zoals ls en grep.
dany@pindabook:~$ man ls
Dit is volgens de handleiding (man) de exitstatuscode van ls opdracht.
De afsluitwaarde is:
0 indien OK,
1 bij kleine problemen (bijv. geen toegang tot een submap),
2 bij serieuze problemen (bijv. geen toegang tot argument op opdrachtregel)
Druk op de sneltoets q om de handleiding af te sluiten.
En dit voor de grep opdracht.
dany@pindabook:~$ man grep
EIND WAARDE
Normaal is de eind waarde 0 als er overeenkomsten werden gevonden, en 1 als geen overeenkomsten werden
gevonden en 2 als er een fout optrad. Hoewel, als of -q of --quiet of --silent werd gebruikt en een regel
werd gevonden, dan is de eind waarde 0 zelfs als er een fout optrad.
Om te voorkomen dat verschillende scripts verschillende betekenissen hebben voor exit-statuscodes, kun je handmatig jouw eigen aangepaste exit-statuscode voor een bepaald script specificeren met behulp van de exit opdracht.
Houd volgens de algemene regel de waarde 0 gereserveerd voor succesvolle uitvoering en gebruik de waarde tussen 1 tot 255 voor fouten.
Als demonstratie passen we met de nano teksteditor opnieuw ons script aan.
dany@pindabook:~$ nano script.sh
Het volgende is een basisscript dat controleert of de huidige gebruiker root is of niet; als de gebruiker root is, wordt Root gebruiker op het scherm weergegeven met een exitstatuscode van 0 of Geen root gebruiker met een exitstatuscode van 1.
#!/bin/bash
if [[ "$(whoami)" == "root" ]]
then
echo "Root gebruiker"
exit 0
else
echo "Geen root gebruiker"
exit 1
fi
Sla het aangepaste script op, sluit nano en test het nieuwe script:
dany@pindabook:~$ ./script.sh
Geen root gebruiker
dany@pindabook:~$ sudo ./script.sh
[sudo] wachtwoord voor dany:
Root gebruiker

Daar we enkel standaard opdrachten hebben gebruikt, bestaat het opruimen enkel uit het verwijderen van het aangemaakte script:
dany@pindabook:~$ rm script.sh