GNU/Linux >> Znalost Linux >  >> Linux

Jak ladit Bash skripty v Linuxu a Unixu

Ladění vám pomůže opravit chyby ve vašem programu. V tomto článku probereme různé metody ladění bash skriptů v operačních systémech Linux a Unix.

Úvod

V prvních dnech programování jsem strávil hodiny hledáním chyby v kódu a nakonec to může být něco jednoduchého. Možná jste se také setkali se stejnou situací.

Vědět, jak používat správnou techniku ​​ladění, vám pomůže rychle vyřešit chyby. Na rozdíl od jiných jazyků, jako je Python, Java atd., neexistuje pro bash žádný ladicí nástroj, kde byste mohli nastavit body přerušení, překročit kód atd.

Existují některé vestavěné funkce, které pomáhají ladit skripty bash shell. Tyto funkce podrobně uvidíme v nadcházejících sekcích.

Tři způsoby použití možností ladění

Pokud chcete ve svých skriptech povolit možnosti ladění, můžete to udělat třemi způsoby.

1 . Při volání skriptu povolte možnosti ladění z shellu terminálu.

$ bash [ příznaky ladění ] název skriptu

2 . Povolte možnosti ladění předáním příznaků ladění do řádku shebang ve skriptu.

#!/bin/bash [ příznaky ladění ]

3 . Povolte možnosti ladění pomocí set příkaz ze skriptu.

set -o podstatné jméno 
set -u

K čemu slouží příkaz Set?

set command je vestavěný příkaz shellu, který lze použít k ovládání parametrů bash a ke změně chování bash určitými způsoby.

Normálně nebudete spouštět příkazy set z terminálu, abyste změnili chování shellu. Bude široce používán v shellových skriptech buď pro ladění, nebo pro aktivaci bash striktního režimu.

$ typ -a set 
sada je vestavěný shell

Můžete vstoupit do sekce nápovědy příkazu set, abyste věděli, jaké příznaky podporuje a co jednotlivé příznaky dělají.

$ set --help

Ladit část skriptu nebo celý skript

Než se seznámíte s možnostmi ladění, musíte pochopit, že můžete ladit buď celý skript, nebo jen určitou část kódu. Chcete-li povolit a zakázat možnosti ladění, musíte použít příkaz set.

  • set -<debugging-flag> povolí režim ladění.
  • set +<debugging-flag> deaktivuje režim ladění.

Podívejte se na níže uvedený kód. set -x povolí pro skript režim xtrace a set +x deaktivuje režim xtrace. Cokoli, co je mezi set -x a set +x bude spuštěn v režimu ladění xtrace.

O režimu xtrace se dozvíte v nadcházející sekci. Takže pro jakýkoli příznak ladění je jediná věc, kterou si musíte zapamatovat, set - aktivuje režim a set + deaktivuje režim.

#!/bin/bashset -xread -p "Název adresáře předání:" D_OBJECTread -p "Název souboru předání:" F_OBJECTset +xtouch ${D_OBJECT}/${F_OBJECT}

Selhání, pokud není definována žádná proměnná

Při práci s proměnnými v bash , nevýhodou je, že pokud se pokusíme použít nedefinovanou proměnnou, skript se nezdaří s nějakou chybovou hláškou jako "Proměnná není definována" . Místo toho vypíše prázdný řetězec.

Podívejte se na níže uvedený kód, kde získávám vstup od uživatele a ukládám jej do proměnné $OBJECT . Zkusil jsem spustit testovací operátor (-f a -d ) na $OBJECT1 proměnná, která není definována.

#!/bin/bashread -p "Uveďte prosím název objektu:" OBJECTif [[ -f $OBJECT1 ]]poté echo "$OBJECT je soubor"elif [[ -d $OBJECT1 ]]poté echo "$ OBJECT je adresář"fi

Když spustím tento kód, mělo mi to vyvolat chybu, ale nestalo se tak a dokonce i skript skončil s návratovým kódem nula.

Chcete-li toto chování přepsat, použijte -u příznak, který při použití nedefinované proměnné vyvolá chybu.

Znovu spustím stejný kód s nesprávným názvem proměnné, ale tentokrát to vyvolá "Nevázaná proměnná" chyba.

Můžete také nastavit -u pomocí možnosti set příkaz nebo jej předejte jako argument do shebang.

nastavit -u
set -o podstatné jméno

(nebo)

#! /bin/bash -u

Režim Xtrace pro záchranu

Toto je režim, který široce používám, když ladím bash skripty pro logické chyby. Xtrace režim zobrazí kód řádek po řádku, ale s rozšířenými parametry.

V předchozí části, když jsem spustil kód bez -u flag, bylo to úspěšně dokončeno, ale očekával jsem výstup v terminálu. Nyní mohu spustit stejný skript v režimu xtrace a přesně vidět, kde se problém ve skriptu odehrává.

Podívejte se na následující ukázkový kód.

#!/bin/bashread -p "Uveďte prosím název objektu:" OBJECTif [[ -f $OBJECT1 ]]poté echo "$OBJECT je soubor"elif [[ -d $OBJECT1 ]]poté echo "$ OBJECT je adresář"fi

Když spustím výše uvedený kód, nevrátí mi žádný výstup.

K odladění tohoto problému mohu spustit skript v xtrace režimu předáním -x vlajka.

V níže uvedeném výstupu můžete vidět, že proměnné jsou rozbaleny a vytištěny. To mi říká, že jsou k podmíněným příkazům -f přiřazeny prázdné řetězce a -d . Tímto způsobem mohu logicky zkontrolovat a opravit chyby.

Znaménko plus, které vidíte ve výstupu, lze změnit nastavením PS4 proměnná ve skriptu. Ve výchozím nastavení je PS4 nastaveno na (+ ).

$ echo $PS4 
+
$ PS4=" ==> " bash -x debugging.sh

Můžete také nastavit režim Xtrace pomocí příkazu set nebo jej předat jako argument do shebang.

nastavit -x
set -o xtrace

(nebo)

#! /bin/bash -x

Podobně můžete při ladění přesměrovat protokoly ladění Xtrace do souboru namísto jejich tisku na terminál.

Podívejte se na níže uvedený kód. K .log přiřazuji deskriptor souboru 6 soubor a BASH_XTRACEFD="6" přesměruje protokoly ladění xtrace na deskriptor souboru 6.

#!/bin/bashexec 6> redirected_debug.log PS4=' ==> ' BASH_XTRACEFD="6" read -p "Uveďte prosím název objektu:" OBJECTif [[ -f $OBJECT1 ]]poté echo "$ OBJECT je soubor"elif [[ -d $OBJECT1 ]]pak echo "$OBJECT je adresář"fi

Když spustím tento kód místo tisku výstupu xtrace v terminálu, bude přesměrován na .log soubor.

$ cat redirected_debug.log  ==> read -p 'Uveďte prosím název objektu :' OBJECT==> [[ -f '' ]]==> [[ -d '' ]]

Stav výstupu PIPE

Výchozí chování při použití kanálu je, že převezme kód ukončení posledního spuštění příkazu v kanálu. I když předchozí příkazy v kanálu selhaly, spustí se zbytek kanálu.

Podívejte se na níže uvedený příklad. Pokusil jsem se otevřít soubor, který není dostupný, a přidat do něj počet slov program. I když cat příkaz vyvolá chybu, spustí se program pro počítání slov.

Pokud se pokusíte zkontrolovat kód ukončení posledního příkazu potrubí pomocí $? , dostanete nulu jako výstupní kód, který pochází z programu pro počítání slov.

$ cat nofile.txt | wc -l cat:nofile.txt:Žádný takový soubor nebo adresář0
$ echo $? 0

Je-li ve skriptu povolena funkce pipefail, a pokud jakýkoli příkaz vyvolá do kanálu nenulový návratový kód, bude to považováno za návratový kód pro celý kanál. Pipefail můžete povolit přidáním následující vlastnosti set do vašeho skriptu.

set -o pipefail

S tímto přístupem je stále problém. Normálně by se mělo očekávat, že pokud některý příkaz v kanálu selže, skript by se měl ukončit bez spuštění zbytku příkazu v kanálu.

Ale bohužel, i když jakýkoli příkaz selže, následný příkaz v rouře běží. Je to proto, že každý příkaz v kanálu běží ve svém vlastním podslupce. Shell počká, dokud nebudou dokončeny všechny procesy v rouře, a poté vrátí výsledek.

Přísný režim Bash

Pro odstranění všech možných chyb, které jsme viděli v předchozích částech, se doporučuje přidat do každého skriptu následující možnosti.

Všechny tyto možnosti jsme již podrobně probrali v předchozí části.

  • -e flag => Ukončete skript, pokud některý příkaz vyvolá nenulový výstupní kód.
  • -u flag => Pokud je použit nedefinovaný název proměnné, skript selže.
  • pipefail => Pokud některý příkaz v kanálu selže, bude výstupní kód zvažován pro celý kanál.
  • IFS => Vnitřní oddělovač polí, nastavením na nový řádek(\n) a (\t) způsobí rozdělení pouze na nový řádek a kartu.
set -e 
nastavit -u
set -o pipefail

Nebo

set -euo pipefail 
IFS=$'\n\t'

Zachyťte signály pomocí TRAP

Pasti umožňuje zachytit signály do vašeho bash skriptu a podle toho provést některé akce.

Představte si scénář, kdy skript spustíte, ale chcete skript zrušit pomocí CTRL+C stisknutí klávesy. V takovém případě SIGINT bude odesláno do vašeho skriptu. Tento signál můžete zachytit a spustit některé příkazy nebo funkce.

Podívejte se na níže uvedený pseudo kód. Vytvořil jsem funkci nazvanou cleanup, která se spustí, když SIGINT je předán skriptu.

trap 'cleanup' TERM INTfunction cleanup(){ echo "Probíhá čištění, protože uživatel spustil CTRL + C" }

Můžete použít trap "DEBUG", který lze použít k opakovanému provádění příkazu ve skriptu. Chová se tak, že každý příkaz spuštěný v pasti skriptu spustí přidruženou funkci nebo příkaz.

Můžete to pochopit pomocí níže uvedeného příkladu.

#!/bin/bashtrap 'printf "${LINENO} ==> DIR_NAME=${D_OBJECT}; FILE_NAME=${F_OBJECT}; FILE_CREATED=${FILE_C} \n"' DEBUGread -p "Přejít název adresáře :" D_OBJECTread -p "Přejít Název souboru :" F_OBJECTtouch ${D_OBJECT}/${F_OBJECT} &&FILE_C="Ano"exit 0

Jedná se o jednoduchý program, který získává vstup od uživatele a vytváří soubor a adresář. Příkaz trap se spustí pro každý příkaz ve skriptu a vypíše předané argumenty a stav vytvoření souboru.

Podívejte se na níže uvedený výstup. Pro každý řádek ve skriptu se spustí past a proměnné se odpovídajícím způsobem aktualizují.

Vytiskněte kód pomocí podrobného režimu

V podrobném režimu bude kód vytištěn před vrácením výsledku. Pokud program vyžaduje interaktivní vstup, v takovém případě bude vytištěn pouze tento řádek následovaný blokem kódů.

Podívejte se na následující program. Jedná se o jednoduchý program, který získá objekt od uživatele a pomocí podmíněného příkazu zkontroluje, zda předávaný objekt je soubor nebo adresář .

#!/bin/bashread -p "Uveďte prosím název objektu:" OBJECTif [[ -f $OBJECT ]]poté echo "$OBJECT je soubor"elif [[ -d $OBJECT ]]poté echo "$ OBJECT je adresář"fi

Když spustím výše uvedený kód, nejprve vytiskne kód a poté počká na vstup uživatele, jak je znázorněno níže.

Jakmile předám objekt, vytiskne se zbytek kódu a následuje výstup.

Můžete také nastavit podrobný režim pomocí set nebo v shebang .

nastavit -v
set -o verbose

(nebo)

#! /bin/bash -v

Můžete také kombinovat podrobný režim s jinými režimy.

set -vx # Verbose a Xtrace Mode 
set -uv # Podrobný a režim Unset

Ověření syntaxe – režim noexec

Doposud jsme viděli, jak pracovat s logickými chybami ve skriptu. V této části probereme syntaktické chyby.

Syntaktické chyby jsou v programech velmi časté. Možná jste vynechali citaci nebo se vám nepodařilo opustit smyčku atd. Můžete použít "-n příznak ", který se nazývá noexec mode pro ověření syntaxe před spuštěním programu.

Spustím níže uvedený kód a ověřím syntaxi.

#!/bin/bashTOOLS=( htop peek tilix vagrant shutter )pro TOOL v "${TOOLS[@]" do echo "--------------INSTALACE:${TOOL }---------------------------" apt install ${TOOL} -y#done

V tomto programu jsou dvě chyby. Za prvé se mi nepodařilo zavřít složené závorky v "for loop “ a za druhé done klíčové slovo je zakomentováno, což by mělo znamenat konec smyčky.

Když spustím tento program, zobrazí se mi následující chybové zprávy ukazující na chybějící složenou závorku a klíčové slovo hotovo . Někdy číslo řádku uvedené v chybové zprávě nebude obsahovat žádné chyby, které byste měli hledat, abyste našli skutečnou chybu.

$ bash -n ./debugging.sh ./debugging.sh:řádek 6:neočekávaný EOF při hledání shody `"'./debugging.sh:řádek 8:chyba syntaxe:neočekávaný konec souboru

Je třeba poznamenat, že ve výchozím nastavení při spuštění skriptu bash ověří syntaxi a vyvolá tyto chyby i bez použití režimu noexec.

Případně můžete také použít set příkaz nebo shebang k použití noexec režimu.

set -n set -o noexec

Nebo,

#! /bin/bash -n

Existuje několik externích nástrojů, které stojí za to se podívat na ladění skriptů. Jedním z takových nástrojů je Shellcheck . Shellcheck lze také integrovat s oblíbenými textovými editory, jako je vscode, sublime text, Atom.

Závěr

V tomto článku jsem vám ukázal některé způsoby, jak ladit bash skripty. Na rozdíl od jiných programovacích jazyků bash nemá jiné nástroje pro ladění než některé vestavěné možnosti. Někdy budou tyto vestavěné možnosti ladění více než dostačující k dokončení práce.

Příručky skriptování Bash:

  • Skriptování Bash – Analýza argumentů ve skriptech Bash pomocí getopts
  • Jak vytvořit dialogová okna GUI ve skriptech Bash pomocí Zenity v Linuxu a Unixu
  • Bash Scripting – Case Statement
  • Skriptování Bash – podmíněné příkazy
  • Bash Scripting – manipulace s řetězci
  • Skriptování Bash – příkaz Printf s příklady
  • Skriptování Bash – indexované pole s příklady
  • Bash Scripting – Asociativní pole vysvětleno s příklady
  • Bash Scripting – pro smyčku vysvětlenou na příkladech
  • Bash Scripting – smyčka Zatímco a dokud není vysvětlena příklady
  • Přesměrování Bash vysvětleno na příkladech
  • Bash Scripting – proměnné vysvětlené na příkladech
  • Bash Scripting – funkce vysvětlené na příkladech
  • Příkaz Bash Echo vysvětlený s příklady v Linuxu
  • Výukový program Bash Heredoc pro začátečníky

Linux
  1. Jak nastavit statickou IP adresu a nakonfigurovat síť v Linuxu

  2. Jak nastavit, vypsat a odebrat proměnné prostředí v Linuxu

  3. Jak trvale nastavit $PATH na Linux/Unix?

  1. Jak nastavit a vypsat proměnné prostředí v Linuxu

  2. Jak nastavit/vytvořit proměnné prostředí a prostředí v Linuxu

  3. UNIX / Linux :Jak nainstalovat a nakonfigurovat mutt

  1. Jak nainstalovat a nastavit prohlížeč Tor v systému Linux

  2. Jak nastavit a vypsat proměnné prostředí v Linuxu

  3. Jak vytvořit dialogová okna GUI ve skriptech Bash se Zenity v Linuxu a Unixu