Debugging a Bash Script

oversigt

i denne tutorial vil vi se på de forskellige teknikker til debug Bash shell scripts. Bash shell giver ikke nogen indbygget debugger. Der er dog visse kommandoer og konstruktioner, der kan bruges til dette formål.

først vil vi diskutere brugen af kommandoen set for debugging scripts. Derefter kontrollerer vi et par fejlsøgningsspecifikke brugssager ved hjælp af sæt-og trap-kommandoerne. Endelig vil vi præsentere nogle metoder til at debug allerede kører scripts.

Bash Debugging Options

de debugging muligheder i Bash shell kan tændes og slukkes på flere måder. Inden for scripts kan vi enten bruge kommandoen set eller tilføje en mulighed til shebang-linjen. En anden tilgang er imidlertid at eksplicit specificere fejlfindingsindstillingerne i kommandolinjen, mens scriptet udføres. Lad os dykke ned i diskussionen.

2.1. Aktivering af verbose-tilstand

vi kan aktivere verbose-tilstanden ved hjælp af-V-kontakten, som giver os mulighed for at se hver kommando, før den udføres.

for at demonstrere dette, lad os oprette et eksempel script:

#! /bin/bashread -p "Enter the input: " valzero_val=0if then echo "Positive number entered."else echo "The input value is not positive."fi

dette script kontrollerer, om nummeret indtastet som input er positivt.

næste, lad os udføre vores script:

$ bash -v ./positive_check.sh#! /bin/bashread -p "Enter the input: " valEnter the input: -10zero_val=0if then echo "Positive number entered."else echo "The input value is not positive."fiThe input value is not positive.

som vi kan bemærke, udskriver den hver linje i scriptet på terminalen, før det behandles.

vi kan også tilføje-v-indstillingen i shebang-linjen:

#! /bin/bash -v

dette har den samme effekt som eksplicit at kalde et script ved hjælp af bash-v. En anden ækvivalent er at aktivere tilstanden i et script ved hjælp af sæt kommando:

#! /bin/bashset -v

faktisk kan vi bruge en af de måder, der er diskuteret ovenfor, til at aktivere de forskellige kontakter, som vi vil diskutere fremover.

2.2. Syntakskontrol ved hjælp af noeksec-tilstand

der kan være situationer, hvor vi måske ønsker at validere scriptet syntaktisk inden dets udførelse. I så fald kan vi bruge noeksec-tilstanden ved hjælp af indstillingen-n. Som et resultat vil Bash læse kommandoerne, men ikke udføre dem.

lad os udføre vores positive_check.sh script i noeksec-tilstand:

$ bash -n ./positive_check.sh

dette giver et tomt output, da der ikke er nogen syntaksfejl. Nu ændrer vi vores script lidt og fjerner den daværende erklæring:

#! /bin/bashread -p "Enter the input: " valzero_val=0if echo "Positive number entered."else echo "The input value is not positive."fi

dernæst validerer vi det syntaktisk med-n mulighed:

$ bash -n ./positive_check_noexec.sh./positive_check_noexec.sh: line 6: syntax error near unexpected token `else'./positive_check_noexec.sh: line 6: ` else'

som forventet kastede det en fejl, da vi gik glip af den daværende erklæring i hvis-tilstanden.

2.3. I det foregående afsnit testede vi scriptet for syntaksfejl. Men for at identificere logiske fejl vil vi måske spore tilstanden af variabler og kommandoer under udførelsesprocessen. I sådanne tilfælde kan vi udføre scriptet i “eksekveringssporing” – tilstand ved hjælp af indstillingen.

denne tilstand udskriver spor af kommandoer for hver linje, efter at de er udvidet, men før de udføres.

lad os udføre vores positive_check.sh script i eksekveringssporingstilstand:

$ bash -x ./positive_check.sh+ read -p 'Enter the input: ' valEnter the input: 17+ zero_val=0+ ''+ echo 'Positive number entered.'Positive number entered.

her kan vi se den udvidede version af variabler på stdout før udførelse. Det er vigtigt at bemærke, at linjerne forud for + – tegnet genereres af sportilstand.

2.4. Identificering af ikke-indstillede variabler

lad os køre et eksperiment for at forstå standardadfærden for ikke-indstillede variabler i Bash-scripts:

#! /bin/bashfive_val=5two_val=2total=$((five_val+tow_val))echo $total

vi udfører nu ovenstående script:

$ ./add_values.sh5

som vi kan bemærke, er der et problem: scriptet udføres med succes, men output er logisk forkert.

vi udfører nu scriptet med indstillingen-u:

$ bash -u ./add_values.sh./add_values.sh: line 4: tow_val: unbound variable

der er helt sikkert meget mere klarhed nu!

scriptet kunne ikke udføres, da variablen bugs_val ikke er defineret. Vi havde fejlagtigt skrevet to_val som to_val under beregningen af det samlede beløb.

indstillingen-u behandler ikke-indstillede variabler og parametre som en fejl, når du udfører parameterudvidelse. Derfor får vi en fejlmeddelelse om, at en variabel ikke er bundet til værdi, mens du udfører scriptet med-U option

brug sager til Debug Shell Scripts

indtil videre så vi de forskellige kontakter til debugging scripts. Fremover vil vi se på nogle brugssager og metoder til at implementere disse i shell-scripts.

3.1. Ved at kombinere Fejlfindingsindstillinger

for at få bedre indsigt kan vi yderligere kombinere de forskellige indstillinger i set-kommandoen.

lad os udføre vores add_values.sh script med både-v og-u indstillinger aktiveret:

$ bash -uv ./add_values.sh#! /bin/bashfive_val=5two_val=2total=$((five_val+tow_val))./add_values.sh: line 4: tow_val: unbound variable

her, ved at aktivere verbose-tilstanden med-U-indstillingen, kunne vi let identificere udsagnet, der udløser fejlen.

på samme måde kan vi kombinere tilstanden verbose og sporing for at få mere præcise fejlfindingsoplysninger.

som diskuteret tidligere viser indstillingen-v hver linje, før den evalueres, og indstillingen-h viser hver linje, efter at de er udvidet. Derfor kan vi kombinere både-og-v-muligheder for at se, hvordan udsagn ser ud før og efter variable substitutioner.

lad os nu udføre vores positive_check.sh script med-V-tilstand aktiveret:

$ bash -xv ./positive_check.sh#! /bin/bashread -p "Enter the input: " val+ read -p 'Enter the input: ' valEnter the input: 5zero_val=0+ zero_val=0if then echo "Positive number entered."else echo "The input value is not positive."fi+ ''+ echo 'Positive number entered.'Positive number entered.

vi kan observere, at udsagnene er trykt på stdout før og efter variabel ekspansion.

3.2. Debugging specifikke dele af scriptet

Debugging med-eller-V option shell scripts genererer et output for hver sætning på stdout. Der kan dog være situationer, hvor vi måske ønsker at reducere fejlfindingsoplysninger til kun bestemte dele af scriptet. Vi kan opnå det ved at aktivere debug-tilstand, før kodeblokken starter, og senere nulstille den ved hjælp af kommandoen set.

lad os tjekke det med et eksempel:

#! /bin/bashread -p "Enter the input: " valzero_val=0set -xif then echo "Positive number entered."else echo "The input value is not positive."fiset +xecho "Script Ended" 

her kunne vi kun debugge if-betingelsen ved hjælp af set-sætningen, før betingelsen starter. Senere kunne vi nulstille if-tilstanden, når if-blokken slutter ved hjælp af kommandoen set +h.

lad os validere det med output:

$ ./positive_debug.shEnter the input: 7+ ''+ echo 'Positive number entered.'Positive number entered.+ set +xScript Ended

bestemt ser Udgangen mindre rodet ud.

3.3. Omdirigering kun Debug Output til en fil

i det foregående afsnit undersøgte vi, hvordan vi kan begrænse debugging til kun bestemte dele af scriptet. Derfor kunne vi begrænse mængden af output på stdout.

desuden kan vi omdirigere fejlfindingsoplysningerne til en anden fil og lade scriptudgangen udskrive på stdout.

lad os oprette et andet script for at kontrollere det:

#! /bin/bashexec 5> debug.log PS4='$LINENO: ' BASH_XTRACEFD="5" read -p "Enter the input: " valzero_val=0if then echo "Positive number entered."else echo "The input value is not positive."fi

først åbnede vi debug.log fil på Filbeskrivelse (FD) 5 til skrivning ved hjælp af eksekveringskommandoen.

så ændrede vi den specielle skalvariabel PS4. PS4-variablen definerer den prompt, der vises, når vi udfører et shell-script i ekstern tilstand. Standardværdien af PS4 er +. Vi ændrede værdien af PS4-Variablen for at vise linjenumre i fejlfindingsprompten. For at opnå dette brugte vi en anden speciel shell variabel LINENO.

senere tildelte vi FD 5 til Bash-variablen BASH_TRACEFD. I virkeligheden vil Bash nu skrive outputtet på FD5, dvs. debug.logfil. Lad os udføre scriptet:

$ bash -x ./debug_logging.sh+ exec+ PS4='$LINENO: '4: BASH_XTRACEFD=5Enter the input: 2Positive number entered.

som forventet er debugoutputtet ikke skrevet på terminalen. Selvom de første par linjer, indtil FD 5 er tildelt debug output blev udskrevet.

derudover opretter scriptet også en outputfil debug.log, som indeholder fejlfindingsoplysningerne:

$ cat debug.log5: read -p 'Enter the input: ' val6: zero_val=07: ''9: echo 'Positive number entered.'

Debugging Scripts ved hjælp af trap

vi kan bruge DEBUG trap-funktionen i Bash til at udføre en kommando gentagne gange. Den kommando, der er angivet i argumenterne for trap-kommandoen, udføres før hver efterfølgende erklæring i scriptet.

lad os illustrere dette med et eksempel:

#! /bin/bashtrap 'echo "Line- ${LINENO}: five_val=${five_val}, two_val=${two_val}, total=${total}" ' DEBUGfive_val=5two_val=2total=$((five_val+two_val))echo "Total is: $total"total=0 && echo "Resetting Total"

i dette eksempel specificerede vi echo-kommandoen for at udskrive værdierne for variabler five_val, to_val og total. Derefter sendte vi denne ekko-erklæring til fældekommandoen med DEBUG-signalet. I virkeligheden, før udførelsen af hver kommando i scriptet, værdierne af variabler bliver udskrevet.

lad os kontrollere det genererede output:

$ ./trap_debug.shLine- 3: five_val=, two_val=, total=Line- 4: five_val=5, two_val=, total=Line- 5: five_val=5, two_val=2, total=Line- 6: five_val=5, two_val=2, total=7Total is: 7Line- 7: five_val=5, two_val=2, total=7Line- 7: five_val=5, two_val=2, total=0Resetting Total

Debugging allerede kører Scripts

hidtil har vi præsenteret metoder til debug shell scripts under udførelsen af dem. Nu skal vi se på måder at debugge et allerede kørende script på.

overvej et eksempel på kørende script, der udfører søvn i en uendelig Mens loop:

#! /bin/bashwhile :do sleep 10 & echo "Sleeping for 4 seconds.." sleep 4done

ved hjælp af pstree-kommandoen kan vi kontrollere de underordnede processer, der er forked af vores script sleep.sh:

$ pstree -pinit(1)─┬─init(148)───bash(149)───sleep.sh(372)─┬─sleep(422) │ ├─sleep(424) │ └─sleep(425) ├─init(213)───bash(214)───pstree(426) └─{init}(7)

vi brugte en ekstra mulighed-p til at udskrive proces-id ‘ erne sammen med procesnavne. Derfor er vi i stand til at indse, at scriptet venter på barnets processer (søvn) at fuldføre.

nogle gange vil vi måske se nærmere på de operationer, der udføres af vores processer. I sådanne tilfælde kan vi bruge strace-kommandoen til at spore de igangværende systemopkald:

$ sudo strace -c -fp 372strace: Process 372 attachedstrace: Process 789 attachedstrace: Process 790 attached^Cstrace: Process 372 detachedstrace: Process 789 detachedstrace: Process 790 detached% time seconds usecs/call calls errors syscall------ ----------- ----------- --------- --------- ----------------100.00 0.015625 5208 3 wait4 0.00 0.000000 0 6 read 0.00 0.000000 0 1 write 0.00 0.000000 0 39 close 0.00 0.000000 0 36 fstat 0.00 0.000000 0 38 mmap 0.00 0.000000 0 8 mprotect 0.00 0.000000 0 2 munmap 0.00 0.000000 0 6 brk 0.00 0.000000 0 16 rt_sigaction 0.00 0.000000 0 20 rt_sigprocmask 0.00 0.000000 0 1 rt_sigreturn 0.00 0.000000 0 6 6 access 0.00 0.000000 0 1 dup2 0.00 0.000000 0 2 getpid 0.00 0.000000 0 2 clone 0.00 0.000000 0 2 execve 0.00 0.000000 0 2 arch_prctl 0.00 0.000000 0 37 openat------ ----------- ----------- --------- --------- ----------------100.00 0.015625 228 6 total

her brugte vi muligheden-p til at vedhæfte proces-id ‘ et (372), dvs.vores script i udførelse. Derudover brugte vi også-f mulighed for at knytte til alle sine barn processer. Bemærk, at kommandoen strace genererer output for hvert systemopkald. Derfor brugte vi-C-indstillingen til at udskrive en oversigt over systemopkaldene ved afslutningen af strace.

konklusion

i denne tutorial studerede vi flere teknikker til fejlfinding af et shell-script.

i begyndelsen diskuterede vi de forskellige muligheder for set command og deres brug til debugging scripts. Derefter implementerede vi flere casestudier for at studere en kombination af fejlfindingsmuligheder. Ved siden af dette undersøgte vi også måder at begrænse debugoutput og omdirigere det til en anden fil.

dernæst præsenterede vi et brugstilfælde af trap-kommandoen og DEBUG-signalet til debugging-scenarier. Endelig tilbød vi et par tilgange til debug allerede kørende scripts.

Skriv et svar

Din e-mailadresse vil ikke blive publiceret.

Previous post Trodser sin Konge: hvordan slaget ved Arsuf blev vundet
Next post fugleperspektiv fotograferingstips