Hvordan spore utførelse av kommandoer i Shell Script med Shell Tracing


I denne artikkelen av shell script debugging serien vil vi forklare den tredje shell script debugging modusen, det vil si shell tracing og se på noen eksempler for å demonstrere hvordan det fungerer, og hvordan det kan brukes.

Den forrige delen av denne serien kaster tydelig lys over de to andre shell script-feilsøkingsmodusene: detaljert modus og syntakskontrollmodus med enkle å forstå eksempler på hvordan man aktiverer shell script debugging i disse modusene.

  1. Slik aktiverer du Shell Script Debugging Mode i Linux – Del 1
  2. Hvordan utfører du syntakskontroll-feilsøkingsmodus i Shell-skript – del 2

Shell-sporing betyr ganske enkelt å spore utførelsen av kommandoene i et shell-skript. For å slå på skallsporing, bruk -x feilsøkingsalternativet.

Dette leder skallet til å vise alle kommandoer og deres argumenter på terminalen etter hvert som de utføres.

Vi vil bruke sys_info.sh shell-skriptet nedenfor, som kort skriver ut systemdato og -klokkeslett, antall brukere pålogget og systemets oppetid. Den inneholder imidlertid syntaksfeil som vi må finne og rette.

#!/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

Lagre filen og gjør skriptet kjørbart. Skriptet kan bare kjøres med root, bruk derfor sudo-kommandoen for å kjøre det som nedenfor:

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

Fra utdataene ovenfor kan vi observere at en kommando først utføres før utdata erstattes som verdien av en variabel.

For eksempel ble datoen først utført, og utdataene ble erstattet med verdien av variabelen DATE.

Vi kan utføre syntakskontroll for kun å vise syntaksfeilene som følger:

$ sudo bash -n sys_info.sh 

Hvis vi ser kritisk på skallskriptet, vil vi innse at if-setningen mangler et avsluttende fi-ord. Derfor, la oss legge det til, og det nye skriptet skal nå se slik ut:

#!/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

Lagre filen igjen og påkall den som root og utfør litt syntakskontroll:

$ sudo bash -n sys_info.sh

Resultatet av syntakskontrolloperasjonen ovenfor viser fortsatt at det er en feil til i skriptet vårt på linje 21. Så vi har fortsatt litt syntakskorrigering å gjøre.

Hvis vi ser gjennom skriptet analytisk en gang til, skyldes feilen på linje 21 et manglende avsluttende dobbeltanførselstegn (”) i den siste ekkokommandoen i print_sys_info-funksjonen .

Vi vil legge til det avsluttende doble anførselstegn i ekko-kommandoen og lagre filen. Det endrede skriptet er nedenfor:

#!/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

Sjekk nå skriptet syntaktisk en gang til.

$ sudo bash -n sys_info.sh

Kommandoen ovenfor vil ikke produsere noe utdata fordi skriptet vårt nå er syntaktisk korrekt. Vi kan like godt spore utførelsen av skriptet for andre gang, og det burde fungere bra:

$ sudo bash -x sys_info.sh

Kjør nå skriptet.

$ sudo ./sys_info.sh

Viktigheten av sporing av Shell-skriptutførelse

Shell-skriptsporing hjelper oss med å identifisere syntaksfeil og enda viktigere, logiske feil. Ta for eksempel check_root-funksjonen i sys_info.sh-skallskriptet, som er ment å avgjøre om en bruker er root eller ikke, siden skriptet kun er tillatt å bli utført av superbrukeren.

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

Magien her styres av if-setningen-uttrykket [ \$UID\ -ne \$ROOT_ID\ ], når vi ikke bruker den passende numeriske operatoren (-ne i dette tilfellet, som betyr ikke like ), ender vi opp med en mulig logisk feil.

Forutsatt at vi brukte -eq ( betyr lik), vil dette tillate enhver systembruker så vel som rotbruker å kjøre skriptet, derav en logisk feil.

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

Merk: Som vi så på før i starten av denne serien, kan den innebygde kommandoen set shell aktivere feilsøking i en bestemt del av et shell-skript.

Derfor vil linjen nedenfor hjelpe oss med å finne denne logiske feilen i funksjonen ved å spore utførelsen:

Skriptet med en logisk feil:

#!/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

Lagre filen og påkall skriptet, vi kan se at en vanlig systembruker kan kjøre skriptet uten sudo som i utdataene nedenfor. Dette er fordi verdien av USER_ID er 100 som ikke er lik root ROOT_ID som er 0.

$ ./sys_info.sh

Vel, det er det for nå, vi har kommet til slutten av shell script debugging-serien, svarskjemaet nedenfor kan brukes til å svare på spørsmål eller tilbakemeldinger til oss, angående denne veiledningen eller hele 3-delt serien.