Si të përdorni set dhe pipefail në skriptet Bash në Linux
Komandat set
dhe pipefail
Linux diktojnë se çfarë ndodh kur ndodh një dështim në një skript Bash. Ka më shumë për të menduar sesa duhet të ndalet ose duhet të vazhdojë.
Skriptet Bash dhe kushtet e gabimit
Skriptet e guaskës Bash janë të shkëlqyera. Ata janë të shpejtë për të shkruar dhe nuk kanë nevojë për përpilim. Çdo veprim i përsëritur ose me shumë faza që duhet të kryeni mund të mbështillet në një skenar të përshtatshëm. Dhe për shkak se skriptet mund të thërrasin ndonjë nga shërbimet standarde të Linux, nuk jeni të kufizuar në aftësitë e vetë gjuhës së guaskës.
Por problemet mund të lindin kur telefononi një program ose program të jashtëm. Nëse dështon, programi i jashtëm do të mbyllet dhe do të dërgojë një kod kthimi në guaskë dhe madje mund të printojë një mesazh gabimi në terminal. Por skenari juaj do të vazhdojë të përpunohet. Ndoshta kjo nuk është ajo që keni dashur. Nëse ndodh një gabim në fillim të ekzekutimit të skriptit, mund të çojë në probleme më të këqija nëse pjesa tjetër e skriptit lejohet të ekzekutohet.
Ju mund të kontrolloni kodin e kthimit nga çdo proces i jashtëm ndërsa përfundojnë, por kjo bëhet e vështirë kur proceset futen në procese të tjera. Kodi i kthimit do të jetë nga procesi në fund të tubit, jo ai në mes që dështoi. Sigurisht, gabime mund të ndodhin edhe brenda skriptit tuaj, të tilla si përpjekja për të hyrë në një variabël të pa inicializuar.
Komandat set
dhe pipefile
ju lejojnë të vendosni se çfarë ndodh kur ndodhin gabime si këto. Ato gjithashtu ju lejojnë të zbuloni gabimet edhe kur ato ndodhin në mes të një zinxhiri tubash.
Ja se si t'i përdorni ato.
Demonstrimi i problemit
Këtu është një skenar i parëndësishëm Bash. Ai i bën jehonë dy rreshtave të tekstit në terminal. Ju mund ta ekzekutoni këtë skript nëse e kopjoni tekstin në një redaktues dhe e ruani si script-1.sh.
#!/bin/bash
echo This will happen first
echo This will happen second
Për ta bërë atë të ekzekutueshëm, do t'ju duhet të përdorni chmod
:
chmod +x script-1.sh
Ju do të duhet ta ekzekutoni atë komandë në çdo skript nëse dëshironi t'i ekzekutoni ato në kompjuterin tuaj. Le të ekzekutojmë skenarin:
./script-1.sh
Dy rreshtat e tekstit dërgohen në dritaren e terminalit siç pritej.
Le ta modifikojmë pak skriptin. Ne do t'i kërkojmë ls
të listojë detajet e një skedari që nuk ekziston. Kjo do të dështojë. Ne e ruajtëm këtë si script-2.sh dhe e bëmë të ekzekutueshme.
#!/bin/bash
echo This will happen first
ls imaginary-filename
echo This will happen second
Kur ekzekutojmë këtë skript, shohim mesazhin e gabimit nga ls
.
./script-2.sh
Megjithëse komanda ls
dështoi, skripti vazhdoi të ekzekutohej. Dhe edhe pse ka pasur një gabim gjatë ekzekutimit të skenarit, kodi i kthimit nga skripti në guaskë është zero, gjë që tregon sukses. Ne mund ta kontrollojmë këtë duke përdorur echo dhe variablin $?
që mban kodin e fundit të kthimit të dërguar në shell.
echo $?
Zero që raportohet është kodi i kthimit nga jehona e dytë në skenar. Pra, ka dy çështje me këtë skenar. E para është se skripti kishte një gabim, por ai vazhdoi të funksiononte. Kjo mund të çojë në probleme të tjera nëse pjesa tjetër e skenarit pret ose varet nga veprimi që dështoi në të vërtetë kishte sukses. Dhe e dyta është se nëse një skenar ose proces tjetër duhet të kontrollojë suksesin ose dështimin e këtij skenari, ai do të marrë një lexim të rremë.
Seti -e Opsioni
Opsioni set -e
(dalje) shkakton daljen e një skripti nëse ndonjë nga proceset që ai quan gjeneron një kod kthimi jo zero. Çdo gjë jo zero konsiderohet si një dështim.
Duke shtuar opsionin set -e
në fillim të skriptit, ne mund të ndryshojmë sjelljen e tij. Ky është script-3.sh.
#!/bin/bash
set -e
echo This will happen first
ls imaginary-filename
echo This will happen second
Nëse e ekzekutojmë këtë skript, do të shohim efektin e set -e
.
./script-3.sh
echo $?
Skripti është ndalur dhe kodi i kthimit i dërguar në shell është një vlerë jo zero.
Ballafaqimi me dështimet në tubacione
Tubacionet i shtojnë më shumë kompleksitet problemit. Kodi i kthimit që del nga një sekuencë komandash me tubacione është kodi i kthimit nga komanda e fundit në zinxhir. Nëse ka një dështim me një komandë në mes të zinxhirit, ne do të kthehemi në shesh. Kodi i kthimit humbet dhe skripti do të vazhdojë të përpunohet.
Ne mund të shohim efektet e komandave të tubacioneve me kode të ndryshme kthimi duke përdorur predha të integruara true
dhe false
. Këto dy komanda nuk bëjnë më shumë sesa gjenerojnë një kod kthimi përkatësisht zero ose një.
true
echo $?
false
echo $?
Nëse futim false
në true
—me false
që përfaqëson një proces të dështuar—ne marrim kodin e kthimit të true
të zero.
false | true
echo $?
Bash ka një variabël grupi të quajtur PIPESTATUS
, dhe kjo kap të gjitha kodet e kthimit nga çdo program në zinxhirin e tubave.
false | true | false | true
echo "${PIPESTATUS[0]} ${PIPESTATUS[1]} ${PIPESTATUS[2]} ${PIPESTATUS[3]}"
PIPESTATUS
ruan vetëm kodet e kthimit deri sa të ekzekutohet programi tjetër dhe përpjekja për të përcaktuar se cili kod kthimi shkon me cilin program mund të bëhet shumë i çrregullt shumë shpejt.
Këtu hyjnë set -o
(opsionet) dhe pipefail
. Ky është script-4.sh. Kjo do të përpiqet të përcjellë përmbajtjen e një skedari që nuk ekziston në wc
.
#!/bin/bash
set -e
echo This will happen first
cat script-99.sh | wc -l
echo This will happen second
Kjo dështon, siç e prisnim.
./script-4.sh
echo $?
Zero e parë është dalja nga wc
, duke na thënë se nuk ka lexuar asnjë rresht për skedarin që mungon. Zero e dytë është kodi i kthimit nga komanda e dytë echo
.
Ne do të shtojmë në -o pipefail
, do ta ruajmë si script-5.sh dhe do ta bëjmë të ekzekutueshëm.
#!/bin/bash
set -eo pipefail
echo This will happen first
cat script-99.sh | wc -l
echo This will happen second
Le ta ekzekutojmë atë dhe të kontrollojmë kodin e kthimit.
./script-5.sh
echo $?
Skripti ndalet dhe komanda e dytë echo
nuk ekzekutohet. Kodi i kthimit i dërguar në guaskë është një, duke treguar saktë një dështim.
Kapja e variablave të painitializuar
Variablat e pa inicializuar mund të jenë të vështira për t'u dalluar në një skenar të botës reale. Nëse përpiqemi të echo
vlerën e një ndryshoreje të painitializuar, echo
thjesht printon një rresht bosh. Nuk nxjerr një mesazh gabimi. Pjesa tjetër e skenarit do të vazhdojë të ekzekutohet.
Ky është script-6.sh.
#!/bin/bash
set -eo pipefail
echo "$notset"
echo "Another echo command"
Ne do ta drejtojmë atë dhe do të vëzhgojmë sjelljen e tij.
./script-6.sh
echo $?
Skripti kalon mbi variablin e painitializuar dhe vazhdon të ekzekutohet. Kodi i kthimit është zero. Përpjekja për të gjetur një gabim si ky në një skenar shumë të gjatë dhe të ndërlikuar mund të jetë shumë i vështirë.
Ne mund ta bllokojmë këtë lloj gabimi duke përdorur opsionin set -u
(unset). Ne do ta shtojmë atë në koleksionin tonë në rritje të opsioneve të vendosura në krye të skenarit, do ta ruajmë si script-7.sh dhe do ta bëjmë të ekzekutueshëm.
#!/bin/bash
set -eou pipefail
echo "$notset"
echo "Another echo command"
Le të ekzekutojmë skenarin:
./script-7.sh
echo $?
Ndryshorja e pa inicializuar zbulohet, skripti ndalet dhe kodi i kthimit vendoset në një.
Opsioni -u
(i pavendosur) është mjaftueshëm inteligjent që të mos aktivizohet nga situata ku mund të ndërveproni në mënyrë legjitime me një variabël të pa inicializuar.
Në script-8.sh, skripti kontrollon nëse ndryshorja New_Var
është inicializuar apo jo. Ju nuk dëshironi që skenari të ndalet këtu, në një skenar të botës reale ju do të kryeni përpunim të mëtejshëm dhe do të përballeni vetë me situatën.
Vini re se ne kemi shtuar opsionin -u
si opsionin e dyta në deklaratën e setit. Opsioni -o pipefail
duhet të jetë i fundit.
#!/bin/bash
set -euo pipefail
if [ -z "${New_Var:-}" ]; then
echo "New_Var has no value assigned to it."
fi
Në script-9.sh, variabli i painitializuar testohet dhe nëse është i painitializuar, në vend të tij jepet një vlerë e paracaktuar.
#!/bin/bash
set -euo pipefail
default_value=484
Value=${New_Var:-$default_value}
echo "New_Var=$Value"
Skriptet lejohen të kalojnë deri në përfundimin e tyre.
./script-8.sh
./script-9.sh
E vulosur me x
Një tjetër opsion i dobishëm për t'u përdorur është opsioni set -x
(ekzekutoni dhe printoni). Kur jeni duke shkruar skenarë, kjo mund të jetë një shpëtim. ai i printon komandat dhe parametrat e tyre gjatë ekzekutimit të tyre.
Kjo ju jep një formë të shpejtë të përafërt dhe të gatshme të gjurmës së ekzekutimit. Izolimi i të metave logjike dhe zbulimi i defekteve bëhet shumë, shumë më i lehtë.
Ne do të shtojmë opsionin set -x në script-8.sh, do ta ruajmë atë si script-10.sh dhe do ta bëjmë atë të ekzekutueshëm.
#!/bin/bash
set -euxo pipefail
if [ -z "${New_Var:-}" ]; then
echo "New_Var has no value assigned to it."
fi
Drejtojeni për të parë linjat e gjurmës.
./script-10.sh
Zbulimi i gabimeve në këto skripta shembuj të parëndësishëm është i lehtë. Kur filloni të shkruani skenarë më të përfshirë, këto opsione do të provojnë vlerën e tyre.