Zoeken op website

Hoe u de uitvoering van opdrachten in Shell Script kunt traceren met Shell Tracing


In dit artikel over de debugging-serie van shell-scripts zullen we de derde debugging-modus van shell-scripts uitleggen, dat wil zeggen shell-tracering, en enkele voorbeelden bekijken om te demonstreren hoe deze werkt en hoe deze kan worden gebruikt.

Het vorige deel van deze serie werpt duidelijk licht op de twee andere foutopsporingsmodi voor shellscripts: uitgebreide modus en syntaxiscontrole modus met gemakkelijk te begrijpen voorbeelden van hoe shell kan worden ingeschakeld scriptfoutopsporing in deze modi.

  1. Hoe u de Shell Script-foutopsporingsmodus in Linux kunt inschakelen - Deel 1
  2. Syntaxiscontrole uitvoeren in de foutopsporingsmodus in Shell-scripts - Deel 2

Shell-tracering betekent eenvoudigweg het traceren van de uitvoering van de opdrachten in een shell-script. Om shell-tracering in te schakelen, gebruikt u de foutopsporingsoptie -x.

Dit geeft de shell de opdracht om alle opdrachten en hun argumenten op de terminal weer te geven terwijl ze worden uitgevoerd.

We zullen het onderstaande sys_info.sh shell-script gebruiken, dat kort uw systeemdatum en -tijd, het aantal ingelogde gebruikers en de uptime van het systeem afdrukt. Het bevat echter syntaxisfouten die we moeten vinden en corrigeren.

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;    
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME
}

check_root
print_sys_info

exit 0

Sla het bestand op en maak het script uitvoerbaar. Het script kan alleen via root worden uitgevoerd. Gebruik daarom de opdracht sudo om het uit te voeren, zoals hieronder:

chmod +x sys_info.sh
sudo bash -x sys_info.sh

Uit de bovenstaande uitvoer kunnen we opmaken dat een opdracht eerst wordt uitgevoerd voordat de uitvoer ervan wordt vervangen door de waarde van een variabele.

De datum werd bijvoorbeeld voor het eerst uitgevoerd en de uitvoer ervan werd vervangen door de waarde van de variabele DATE.

We kunnen syntaxiscontrole uitvoeren om alleen de syntaxisfouten als volgt weer te geven:

sudo bash -n sys_info.sh 

Als we kritisch naar het shellscript kijken, zullen we ons realiseren dat de if-instructie een afsluitend fi-woord mist. Laten we het daarom toevoegen en het nieuwe script zou er nu als volgt uit moeten zien:

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
   fi    
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME
}

check_root
print_sys_info

exit 0

Sla het bestand opnieuw op, roep het aan als root en voer wat syntaxiscontrole uit:

sudo bash -n sys_info.sh

Het resultaat van onze syntaxiscontrole hierboven laat nog steeds zien dat er nog een bug in ons script zit op regel 21. We moeten dus nog wat syntaxiscorrectie uitvoeren.

Als we het script nog een keer analytisch doornemen, is de fout op regel 21 te wijten aan een ontbrekend dubbel aanhalingsteken ( ”) in het laatste echo-commando binnen de print_sys_info-functie.

We voegen het afsluitende dubbele aanhalingsteken toe aan het echo commando en slaan het bestand op. Het gewijzigde script staat hieronder:

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME"
}

check_root
print_sys_info

exit 0

Controleer het script nu nog een keer syntactisch.

sudo bash -n sys_info.sh

De bovenstaande opdracht levert geen uitvoer op omdat ons script nu syntactisch correct is. We kunnen de uitvoering van het script net zo goed voor een tweede keer traceren en het zou goed moeten werken:

sudo bash -x sys_info.sh

Voer nu het script uit.

sudo ./sys_info.sh

Het belang van tracering van de uitvoering van shell-scripts

Shell-scripttracering helpt ons syntaxisfouten en, nog belangrijker, logische fouten te identificeren. Neem bijvoorbeeld de functie check_root in het shellscript sys_info.sh, dat bedoeld is om te bepalen of een gebruiker root is of niet, aangezien het script alleen mag worden uitgevoerd door de supergebruiker.

check_root(){
    if [ "$UID" -ne "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

De magie hier wordt bepaald door de if-instructie expressie [ "$UID" -ne "$ROOT_ID" ], zodra we niet de geschikte numerieke operator () gebruiken -ne in dit geval, wat betekent niet gelijk ), krijgen we een mogelijke logische fout.

Ervan uitgaande dat we -eq (betekent gelijk aan) gebruikten, zou dit elke systeemgebruiker en de rootgebruiker in staat stellen het script uit te voeren, wat een logische fout veroorzaakt.

check_root(){
    if [ "$UID" -eq "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

Opmerking: Zoals we eerder hebben gezien aan het begin van deze serie, kan het ingebouwde commando set shell het debuggen activeren in een bepaalde sectie van een shellscript.

Daarom zal de onderstaande regel ons helpen deze logische fout in de functie te vinden door de uitvoering ervan te traceren:

Het script met een logische fout:

#!/bin/bash
#script to print brief system info

ROOT_ID="0"

DATE=`date`
NO_USERS=`who | wc -l`
UPTIME=`uptime`

check_root(){
    if [ "$UID" -eq "$ROOT_ID" ]; then
        echo "You are not allowed to execute this program!"
        exit 1;
    fi
}

print_sys_info(){
    echo "System Time    : $DATE"
    echo "Number of users: $NO_USERS"
    echo "System Uptime  : $UPTIME"
}

#turning on and off debugging of check_root function
set -x ; check_root;  set +x ;
print_sys_info

exit 0

Sla het bestand op en roep het script aan. We kunnen zien dat een gewone systeemgebruiker het script kan uitvoeren zonder sudo, zoals in de onderstaande uitvoer. Dit komt omdat de waarde van USER_ID 100 is, wat niet gelijk is aan de root ROOT_ID, die 0 is.

./sys_info.sh

Nou, dat is het voor nu, we zijn aan het einde gekomen van de serie foutopsporing in shell-scripts. Het onderstaande antwoordformulier kan worden gebruikt om eventuele vragen of feedback aan ons te richten over deze handleiding of de hele driedelige serie.