áttekintés
ebben az oktatóanyagban megvizsgáljuk a Bash shell szkriptek hibakeresésének különféle technikáit. A Bash shell nem nyújt beépített hibakeresőt. Vannak azonban bizonyos parancsok és konstrukciók, amelyeket erre a célra lehet használni.
először a set parancs hibakeresési parancsainak használatát tárgyaljuk. Ezt követően néhány hibakeresési konkrét felhasználási esetet ellenőrizünk a set and trap parancsok segítségével. Végül bemutatunk néhány módszert a már futó szkriptek hibakeresésére.
Bash hibakeresési lehetőségek
a Bash shell hibakeresési lehetőségei többféle módon be-és kikapcsolhatók. A szkripteken belül használhatjuk a set parancsot, vagy hozzáadhatunk egy opciót a shebang sorhoz. Egy másik megközelítés azonban a hibakeresési lehetőségek kifejezett megadása a parancssorban a parancsfájl végrehajtása közben. Merüljünk bele a vitába.
2.1. A verbose mód engedélyezése
a verbose módot a-v kapcsolóval engedélyezhetjük, amely lehetővé teszi az egyes parancsok megtekintését a végrehajtás előtt.
ennek bemutatásához hozzunk létre egy minta szkriptet:
#! /bin/bashread -p "Enter the input: " valzero_val=0if then echo "Positive number entered."else echo "The input value is not positive."fi
ez a parancsfájl ellenőrzi, hogy a bemenetként megadott szám pozitív-e vagy sem.
ezután hajtsuk végre a szkriptünket:
$ 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.
amint észrevehetjük, kinyomtatja a szkript minden sorát a terminálon, mielőtt feldolgoznák.
hozzáadhatjuk a-v opciót is a shebang sorban:
#! /bin/bash -v
ennek ugyanaz a hatása, mint egy szkript explicit meghívása a bash-V használatával. egy másik egyenértékű az, hogy engedélyezzük a szkripten belüli módot a set paranccsal:
#! /bin/bashset -v
valójában a fent tárgyalt módok bármelyikét használhatjuk a különféle kapcsolók engedélyezéséhez, amelyeket a továbbiakban megvitatunk.
2.2. Szintaxisellenőrzés a noexec mód használatával
előfordulhatnak olyan helyzetek, amikor a szkriptet szintaktikailag érvényesíteni kell a végrehajtása előtt. Ha igen, akkor a noexec módot használhatjuk a-n opcióval. Ennek eredményeként a Bash elolvassa a parancsokat, de nem hajtja végre őket.
hajtsuk végre a positive_check.sh szkript noexec módban:
$ bash -n ./positive_check.sh
ez üres kimenetet eredményez, mivel nincsenek szintaktikai hibák. Most egy kicsit módosítjuk a szkriptünket, majd eltávolítjuk a then utasítást:
#! /bin/bashread -p "Enter the input: " valzero_val=0if echo "Positive number entered."else echo "The input value is not positive."fi
ezután szintaktikailag érvényesítjük a-n opcióval:
$ 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'
ahogy az várható volt, hibát dobott, mivel elmulasztottuk a then állítást az if állapotban.
2.3. Hibakeresés Xtrace módban
az előző szakaszban teszteltük a szkriptet szintaktikai hibák szempontjából. De a logikai hibák azonosításához érdemes nyomon követni a változók és parancsok állapotát a végrehajtási folyamat során. Ilyen esetekben a szkriptet xtrace (execution trace) módban hajthatjuk végre a-x opcióval.
ez a mód kinyomtatja a parancsok nyomát az egyes sorokhoz a kibontás után, de a végrehajtás előtt.
hajtsuk végre a positive_check.sh script végrehajtás nyomkövetési módban:
$ bash -x ./positive_check.sh+ read -p 'Enter the input: ' valEnter the input: 17+ zero_val=0+ ''+ echo 'Positive number entered.'Positive number entered.
itt láthatjuk a változók kibővített változatát az stdout-on a végrehajtás előtt. Fontos megjegyezni, hogy a + jel előtti sorokat az xtrace mód generálja.
2.4. A nem beállított változók azonosítása
futtassunk egy kísérletet a nem beállított változók alapértelmezett viselkedésének megértéséhez a Bash szkriptekben:
#! /bin/bashfive_val=5two_val=2total=$((five_val+tow_val))echo $total
most végrehajtjuk a fenti szkriptet:
$ ./add_values.sh5
amint észrevehetjük, van egy probléma: a szkript sikeresen végrehajtott, de a kimenet logikailag helytelen.
most végrehajtjuk a szkriptet a-u opcióval:
$ bash -u ./add_values.sh./add_values.sh: line 4: tow_val: unbound variable
természetesen most sokkal több a tisztánlátás!
a parancsfájl végrehajtása nem sikerült, mivel a tow_val változó nincs definiálva. Mi volt tévesen gépelt two_val mint tow_val kiszámításakor a teljes.
a-u opció hibaként kezeli a nem beállított változókat és paramétereket a paraméterbővítés végrehajtásakor. Következésképpen hibaüzenetet kapunk arról, hogy egy változó nem kötődik az értékhez, miközben a szkriptet a-u opcióval hajtja végre
esetek használata Shell szkriptek hibakereséséhez
eddig láttuk a szkriptek hibakeresésének különféle kapcsolóit. A továbbiakban megvizsgálunk néhány felhasználási esetet és módszert ezek implementálására shell szkriptekben.
3.1. A hibakeresési lehetőségek kombinálása
a jobb betekintés érdekében tovább kombinálhatjuk a set parancs különféle lehetőségeit.
hajtsuk végre a add_values.sh szkript mind a-v, mind az-u opcióval engedélyezve:
$ bash -uv ./add_values.sh#! /bin/bashfive_val=5two_val=2total=$((five_val+tow_val))./add_values.sh: line 4: tow_val: unbound variable
itt a részletes mód engedélyezésével a-u opcióval könnyen azonosíthatjuk a hibát kiváltó utasítást.
hasonlóképpen kombinálhatjuk a részletes és az xtrace módot, hogy pontosabb hibakeresési információkat kapjunk.
amint azt korábban tárgyaltuk, a-v opció az egyes sorokat az értékelés előtt, az-x opció pedig az egyes sorokat a kibontás után jeleníti meg. Ezért kombinálhatjuk mind az-x, mind a-v opciókat, hogy lássuk, hogyan néznek ki az állítások a változó helyettesítések előtt és után.
most hajtsuk végre a positive_check.sh script-x és-v mód engedélyezve:
$ 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.
megfigyelhetjük, hogy az utasítások az stdout-ra vannak nyomtatva a változó bővítése előtt és után.
3.2. A parancsfájl egyes részeinek hibakeresése
hibakeresés-x vagy-v opcióval shell szkriptek kimenetet generál az stdout minden utasításához. Előfordulhatnak azonban olyan helyzetek, amikor a hibakeresési információkat csak a szkript meghatározott részeire szeretnénk csökkenteni. Ezt úgy érhetjük el, hogy engedélyezzük a hibakeresési módot a kódblokk megkezdése előtt, majd később visszaállítjuk a set paranccsal.
nézzük meg egy példával:
#! /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"
itt csak az if feltételt tudtuk hibakeresni a set utasítás használatával a feltétel megkezdése előtt. Később visszaállíthatjuk az xtrace módot, miután az if blokk véget ért a set + x paranccsal.
érvényesítsük a kimenettel:
$ ./positive_debug.shEnter the input: 7+ ''+ echo 'Positive number entered.'Positive number entered.+ set +xScript Ended
természetesen a kimenet kevésbé rendetlennek tűnik.
3.3. Csak a hibakeresési kimenet átirányítása egy fájlba
az előző szakaszban megvizsgáltuk, hogyan korlátozhatjuk a hibakeresést a szkript bizonyos részeire. Következésképpen korlátozhatjuk az stdout kimenetének mennyiségét.
ezenkívül átirányíthatjuk a hibakeresési információkat egy másik fájlba, és hagyhatjuk, hogy a szkript kimenete az stdout-on nyomtasson.
hozzunk létre egy másik szkriptet annak ellenőrzéséhez:
#! /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
először megnyitottuk a hibakeresést.naplófájl a Fájlleíróban (FD) 5 az exec paranccsal történő íráshoz.
ezután megváltoztattuk a PS4 speciális héjváltozót. A PS4 változó meghatározza azt a promptot, amely akkor jelenik meg, amikor egy shell szkriptet futtatunk xtrace módban. A PS4 alapértelmezett értéke +. Megváltoztattuk a PS4 változó értékét, hogy a sorszámokat megjelenítsük a hibakeresési promptban. Ennek eléréséhez egy másik speciális héjváltozót használtunk LINENO.
később hozzárendeltük az FD 5 to bash változót BASH_XTRACEFD. Valójában a Bash most az xtrace kimenetet írja az FD5-re, azaz hibakeresésre.naplófájl. Hajtsuk végre a szkriptet:
$ bash -x ./debug_logging.sh+ exec+ PS4='$LINENO: '4: BASH_XTRACEFD=5Enter the input: 2Positive number entered.
ahogy az várható volt, a hibakeresési kimenetet nem írják a terminálra. Bár, az első néhány sort, amíg FD 5 van rendelve hibakeresés kimenet nyomtatták.
ezenkívül a szkript létrehoz egy kimeneti fájl hibakeresést is.napló, amely tartalmazza a hibakeresési információkat:
$ cat debug.log5: read -p 'Enter the input: ' val6: zero_val=07: ''9: echo 'Positive number entered.'
hibakeresés szkriptek használata trap
tudjuk használni a DEBUG trap funkció Bash, hogy végre egy parancsot ismétlődően. A trap parancs argumentumaiban megadott parancs a parancsfájl minden további utasítása előtt végrehajtásra kerül.
illusztráljuk ezt egy példával:
#! /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"
ebben a példában megadtuk az echo parancsot a five_val, two_val és total változók értékeinek kinyomtatására. Ezt követően átadtuk ezt az echo nyilatkozatot a trap parancsnak a hibakeresési jelzéssel. Valójában a parancsfájl minden parancsának végrehajtása előtt a változók értékei kinyomtatásra kerülnek.
ellenőrizzük a generált kimenetet:
$ ./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
hibakeresés már futó szkriptek
eddig bemutattunk módszereket a shell szkriptek hibakeresésére azok végrehajtása közben. Most megvizsgáljuk a már futó szkript hibakeresésének módjait.
Vegyünk egy minta futó szkriptet, amely végrehajtja az alvást egy végtelen while ciklusban:
#! /bin/bashwhile :do sleep 10 & echo "Sleeping for 4 seconds.." sleep 4done
a pstree parancs segítségével ellenőrizhetjük a szkriptünk által elágazó gyermekfolyamatokat 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)
egy további opciót használtunk-p a folyamatazonosítók nyomtatásához a folyamatnevekkel együtt. Ezért képesek vagyunk felismerni, hogy a szkript arra vár, hogy a gyermek folyamatai (alvás) befejeződjenek.
néha érdemes közelebbről megvizsgálni a folyamataink által végrehajtott műveleteket. Ilyen esetekben a strace paranccsal nyomon követhetjük a folyamatban lévő Linux rendszerhívásokat:
$ 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
itt a-p opciót használtuk a folyamatazonosítóhoz (372), azaz a szkriptünk végrehajtásához. Ezenkívül a-f opciót is használtuk az összes gyermekfolyamathoz való csatoláshoz. Vegye figyelembe, hogy a strace parancs minden rendszerhíváshoz kimenetet generál. Ezért a-c opciót használtuk a rendszerhívások összefoglalójának kinyomtatására a strace befejezésekor.
következtetés
ebben az oktatóanyagban több technikát tanulmányoztunk egy shell szkript hibakeresésére.
kezdetben megvitattuk a set parancs különböző lehetőségeit és a szkriptek hibakeresésének használatát. Ezt követően számos esettanulmányt hajtottunk végre a hibakeresési lehetőségek kombinációjának tanulmányozására. Emellett azt is megvizsgáltuk, hogyan lehet korlátozni a hibakeresési kimenetet, és átirányítani egy másik fájlba.
ezután bemutattuk a trap parancs és a DEBUG signal használatát a hibakeresési forgatókönyvekhez. Végül felajánlottunk néhány megközelítést a már futó szkriptek hibakeresésére.