Basis van shellscripts
BeginnerLes 4 van 7 in Cursus Linux: commandoregel, shellscripts, gebruikers en services
Wat je leert
- Zet een reeks commando's die je steeds opnieuw typt in een scriptbestand, begin het met de juiste interpreterregel en voer het vanuit elke directory uit.
- Zet terugkerende commando's in een scriptbestandSchrijf commando's op volgorde in een bestand met platte tekst, voeg commentaar toe en begin het bestand met een shebangregel die Bash als interpreter aanwijst.
- Voer een script uit en kies waar je het opslaatMaak een script uitvoerbaar, voer het uit via een pad of een interpreter, plaats het in een directory op PATH en weet wanneer een script je huidige shell kan wijzigen.
- Zet terugkerende commando's in een scriptbestand
- Bewaar tekst, getallen en commando-uitvoer in variabelen, lees invoer van de gebruiker en gebruik afscherming zodat spaties en speciale tekens ongewijzigd bij commando's aankomen.
- Maak variabelen, lees hun waarden en exporteer zeKen waarden toe aan shellvariabelen en gebruik ze, kies goede namen, lees invoer van de gebruiker en geef variabelen door aan de programma's die een script start.
- Scherm woorden, variabelen en speciale tekens afKies tussen enkele aanhalingstekens, dubbele aanhalingstekens en backslashes en scherm elke variabele-expansie af zodat spaties en jokertekens in waarden een commando niet kunnen verstoren.
- Vang commando-uitvoer op en reken met gehele getallenSla de uitvoer van een commando op met commandosubstitutie en reken met gehele getallen, bijvoorbeeld om bestandsnamen met een datum te maken en tellers bij te houden.
- Maak variabelen, lees hun waarden en exporteer ze
- Lees de afsluitstatus van commando's en scripts uit en stel die in, koppel vervolgcommando's aan succes of mislukking en spoor fouten op en stop ze voordat ze schade veroorzaken.
- Lees afsluitcodes uit, stel ze in en koppel er vervolgcommando's aanGebruik de afsluitstatus die elk commando teruggeeft, beëindig een script met een betekenisvolle code en voer commando's alleen uit als een eerder commando is geslaagd of mislukt.
- Spoor fouten op en stop een script veiligControleer en traceer een script om fouten te vinden, stuur foutmeldingen naar standaardfoutuitvoer en laat een script stoppen bij mislukte commando's, niet-ingestelde variabelen en mislukte pijplijnen.
- Lees afsluitcodes uit, stel ze in en koppel er vervolgcommando's aan
- Test bestanden, tekst en getallen, kies met if en case wat je doet en herhaal commando's voor lijsten, bestanden en regels met for-, while- en until-lussen.
- Test bestanden, tekenreeksen en getallenSchrijf voorwaarden met test, [ ] en [[ ]] die controleren of bestanden bestaan, tekst en gehele getallen vergelijken en combineer of ontken die voorwaarden.
- Kies acties met if, elif, else en caseVoer met if, elif en else verschillende commando's uit afhankelijk van een voorwaarde en vergelijk met case één waarde met meerdere patronen.
- Herhaal commando's voor lijsten en bestanden met forDoorloop een lijst met woorden, de bestanden die overeenkomen met een patroon, een getallenbereik of de argumenten van een script en verwerk bestandsnamen met spaties.
- Herhaal commando's totdat een voorwaarde verandert met while en untilVoer commando's uit zolang een voorwaarde slaagt of totdat die slaagt, lees een bestand regel voor regel en bestuur lussen met break, continue en sleep.
- Test bestanden, tekenreeksen en getallen
- Geef een script zijn invoer op de commandoregel, lees de argumenten binnen het script, controleer ze en geef standaardwaarden op zodat hetzelfde script voor veel situaties werkt.
- Lees positionele parameters en het aantal argumenten uitGebruik
$0,$1tot en met$9,${10},$#en"$@"om de woorden te lezen die na de naam van een script zijn opgegeven, en gebruikshiftom ze te doorlopen. - Controleer argumenten, toon een gebruiksinstructie en stel standaardwaarden inControleer het aantal en de soort argumenten, toon een gebruiksinstructie en sluit af met een foutcode, gebruik standaardwaarden en verwerk eenvoudige opties.
- Lees positionele parameters en het aantal argumenten uit
- Voer scripts met cron of systemd-timers op vaste tijden of met vaste tussenpozen uit zonder aangemeld te zijn, en controleer of de geplande uitvoeringen plaatsvinden en slagen.
- Plan taken met cronSchrijf crontab-vermeldingen met de vijf tijdvelden, bewerk en toon ze met crontab en bereid scripts voor op de minimale omgeving van cron.
- Plan taken met systemd-timersKoppel een service-unit aan een timerunit, schrijf planningen op basis van de kalender en tussenpozen, schakel de timer in en controleer de volgende uitvoering en de logboeken.
- Plan taken met cron
Shellscripts: uitleg
1Schrijf je eerste Bash-scripts en voer ze uit
Een paar commando's zijn gemakkelijker te herhalen als ze samen in een script staan. Je geeft het bestand een Bash-interpreter, houdt de instructies leesbaar en kiest hoe je het start. Bestandsrechten, zoekpaden voor commando's en kindshells verklaren enkele veelvoorkomende verrassingen: waarom een script met bash werkt maar met ./ mislukt, waarom de naam niet wordt gevonden en waarom wijzigingen van directory in het script je terminal niet verplaatsen.
1.1 Zet terugkerende commando's in een scriptbestand
Een shellscript bewaart een reeks commando's in een bestand met platte tekst. Bash leest de commando's op volgorde, net zoals het commando's leest die je bij een prompt invoert. Een script kan een taak herhalen zonder dat iemand elke stap typt en geeft je één plek om die taak te corrigeren of te verbeteren.
Zet de interpreter op de eerste regel
De shebang vertelt Linux welk programma een uitvoerbaar script moet lezen. Begin een Bash-script met #!/bin/bash. De #! moet uit de eerste twee tekens van het bestand bestaan: er mogen geen spaties of lege regel voor staan. Bash is de Bourne Again Shell. Die wordt op Linux veel gebruikt als interactieve shell en leest ook scriptbestanden.
Een interpreter is een programma dat een andere taal leest en uitvoert. Via hetzelfde mechanisme kiest #!/usr/bin/python3 voor Python en #!/usr/bin/awk -f voor awk. De rest van een Bash-script moet shellcommando's bevatten die Bash begrijpt.
Maak backup-notes.sh in een editor voor platte tekst zoals nano of vi:
#!/bin/bash
# Keep a copy of the notes and show the backup folder.
mkdir -p ~/backup
cp ~/notes.txt ~/backup/
ls -l ~/backup
Bash maakt eerst de bestemmingsdirectory, kopieert daarna de notities en toont vervolgens de inhoud van de bestemming. mkdir -p slaagt ook als de directory al bestaat, zodat een latere uitvoering die kan hergebruiken. Het bronbestand ~/notes.txt moet bestaan om het kopiëren te laten werken. Door de commando's op te slaan maak je dat bronbestand niet aan.
Maak het bestand leesbaar voor mensen
De tweede regel is commentaar. Buiten afgeschermde tekst begint # aan het begin van een woord een commentaarregel; Bash negeert de rest van die regel. Schrijf commentaar over het doel van een stap, bijvoorbeeld waarom een back-up moet worden bewaard. Lege regels en inspringing maken groepen commando's beter zichtbaar. Laat de inspringing consistent blijven als je voorwaarden en lussen toevoegt.
De extensie .sh helpt een lezer een shellscript te herkennen. Linux vereist die extensie niet en door die toe te voegen kies je geen Bash en verleen je geen uitvoerrecht. Een bestand met de naam backup-notes kan dezelfde commando's uitvoeren.
Stem de shell af op de taal
| Eerste regel | Hoe de interpreter wordt gekozen |
|---|---|
#!/bin/bash | Gebruikt Bash op het vaste pad /bin/bash. |
#!/usr/bin/env bash | Gebruikt env om Bash via PATH te vinden. |
#!/bin/sh | Gebruikt sh van het systeem, wat een andere shell kan zijn. |
Op Debian en Ubuntu kiest /bin/sh normaal gesproken dash. Bash-functies zoals [[ ... ]] werken daarin niet. Een Bash-script heeft een Bash-interpreter nodig, ook als eenvoudige commando's toevallig onder beide shells werken. Een bestand something.sh noemen lost een niet-passende shebang niet op.
Herken een probleem met regeleinden
Windows-editors kunnen vóór elk nieuweregelteken een carriage-returnteken opslaan. Op Linux kan dat onzichtbare teken deel worden van het shebangpad. Een fout zoals /bin/bash^M: bad interpreter: No such file or directory wijst op dit probleem, ook al bestaat /bin/bash.
Zet het bestand om naar Unix-regeleinden met dos2unix backup-notes.sh en sla toekomstige scripts daarna in de editor op met Unix-regeleinden. De commando's in het bestand kunnen correct zijn terwijl het extra teken voorkomt dat Linux hun interpreter start.
Belangrijkste punten
- Een script is platte tekst met commando's die op volgorde worden uitgevoerd.
- De shebang moet helemaal aan het begin van het bestand staan en de juiste interpreter aanwijzen.
- Gebruik commentaar en inspringing om het doel en de structuur duidelijk te maken.
- Een
.sh-extensie is een conventie; die kiest geen shell. - Unix-regeleinden voorkomen dat een verborgen carriage-returnteken de shebang onbruikbaar maakt.
1.2 Voer een script uit en kies waar je het opslaat
Bash kan een script rechtstreeks lezen of het script kan als programma worden gestart. Deze manieren verschillen in de rechten die ze nodig hebben en in de keuze van de interpreter. Het pad dat je typt, bepaalt ook of de shell een commando zoekt of één specifiek bestand gebruikt.
Twee manieren om hetzelfde bestand te starten
bash backup-notes.sh
chmod u+x backup-notes.sh
./backup-notes.sh
Het eerste commando start Bash en vraagt die het bestand te lezen. Het script heeft leesrecht nodig; de eigen uitvoerbit is niet vereist. Bash behandelt de shebang als commentaar omdat de interpreter al is gekozen.
Het tweede commando voegt uitvoerrecht toe voor de eigenaar van het bestand. In een rechtenreeks zoals -rwxr--r-- betekent de x van de eigenaar dat het bestand uitvoerbaar is. Het derde commando voert het bestand uit als programma en gebruikt de shebang. Ook chmod +x wordt veel gebruikt; zonder genoemde rechtenklasse beperkt de umask welke klassen uitvoerrecht krijgen. chmod u+x richt zich expliciet op de eigenaar.
Als ./backup-notes.sh “Permission denied” meldt, controleer dan het uitvoerrecht en de toegang tot het pad. Als bash backup-notes.sh werkt, betekent dat niet dat de rechten voor directe uitvoering in orde zijn.
Begrijp hoe commando's worden gezocht
./ betekent de huidige directory. Als een commando een schuine streep bevat, volgt Bash dat pad. Als je een naam zonder schuine streep typt, doorzoekt Bash de directory's in PATH. De huidige directory ontbreekt normaal gesproken in die lijst, dus in de directory van een script staan is niet genoeg om het met alleen de naam uit te voeren.
echo "$PATH"
command -v backup-notes.sh
type backup-notes.sh
PATH is een lijst gescheiden door dubbele punten, zoals /home/sam/.local/bin:/usr/local/bin:/usr/bin:/bin. Het eerste overeenkomende uitvoerbare bestand wordt gebruikt. De laatste twee commando's helpen bepalen wat bij een naam wordt uitgevoerd, ook als er ergens anders op PATH een oudere kopie staat.
Om een persoonlijk script met zijn naam beschikbaar te maken, plaats je het in een directory op je PATH. Veel distributies voegen ~/bin of ~/.local/bin bij het aanmelden toe als die directory bestaat; controleer je eigen PATH. /usr/local/bin is een gebruikelijke locatie voor scripts die gebruikers delen en je hebt beheerdersrechten nodig om erin te schrijven.
Kies een kindshell of de huidige shell
Als je ./settings.sh of bash settings.sh uitvoert, start een Bash-kindproces. De variabelen en directorywijzigingen ervan horen bij dat kindproces. Een script met cd /var/log verplaatst de terminal die het startte niet. Als het eindigt, sta je nog steeds in de oorspronkelijke directory van de terminal.
Inlezen in de huidige shell (sourcing) leest commando's in de huidige shell:
source ./settings.sh
# Equivalent short form:
. ./settings.sh
Gebruik dit voor een instellingenbestand dat bedoeld is om je sessie te wijzigen. Inlezen vereist leesrecht, geen uitvoerrecht, en een shebang start geen afzonderlijke interpreter. Als je een Bash-instellingenbestand inleest, ga je er dus van uit dat de huidige shell Bash-syntaxis begrijpt.
Lees het resultaat van een uitvoering
Direct nadat een script eindigt, toont echo $? de afsluitstatus. Tenzij het script exit met een gekozen code gebruikt, komt de status van het laatste commando. Een geslaagde laatste bestandslijst kan daardoor een eerder mislukte kopieeractie verbergen; met foutcontroles verderop kan het script het werkelijke resultaat van de taak melden.
Belangrijkste punten
bash fileleest een script met Bash;./filevereist uitvoerrecht en gebruikt de shebang.- PATH wordt alleen doorzocht voor commandonamen zonder schuine streep.
- Controleer een commandonaam met
command -voftype. - Uitvoering start een kindshell; inlezen kan de huidige shell wijzigen.
2Sla waarden op in variabelen en scherm ze veilig af
Met variabelen werken dezelfde commando's met wisselende paden, namen en aantallen. Afscherming houdt die waarden intact terwijl Bash een commandoregel opbouwt, zodat een spatie in een naam deel van de naam blijft. Je leest invoer, geeft waarden door aan kindprogramma's, vangt commando-uitvoer op en rekent met gehele getallen. Deze onderdelen werken samen als een script een bestandsnaam met een datum maakt of een doorlopende telling bijhoudt.
2.1 Maak variabelen, lees hun waarden en exporteer ze
Een variabele geeft een waarde een naam zodat hetzelfde script die kan hergebruiken. Bash-variabelen bevatten normaal gesproken tekst, ook als die tekst op een getal lijkt. Je kent de waarde één keer toe en expandeert de naam overal waar een commando die waarde nodig heeft.
Ken waarden toe zonder spaties
city=Lisbon
greeting="Good morning"
echo "$greeting from $city"
De uitvoer is “Good morning from Lisbon”. Er staan geen spaties rond de = van de toekenning. In city = Lisbon behandelt Bash city als een commando en de andere woorden als argumenten. Aanhalingstekens rond "Good morning" houden beide woorden in één waarde.
Gebruik letters, cijfers en underscores in variabelenamen, met een letter of underscore vooraan. Namen zijn hoofdlettergevoelig: file, File en FILE zijn verschillend. Kies namen met kleine letters zoals backup_dir voor waarden die bij je script horen. Zo voorkom je dat je omgevingsvariabelen zoals PATH of HOME vervangt. Als je PATH=/data instelt, verandert het zoeken naar commando's en worden gewone commando's mogelijk niet meer gevonden.
Geef aan waar een naam eindigt
Een dollarteken leidt een expansie in. Accolades geven de grens aan als er direct meer tekst volgt:
file=report
echo "${file}_old"
Dit toont “report_old”. Bij "$file_old" zoekt Bash een variabele met de naam file_old, niet file gevolgd door _old. Zonder set -u expandeert een niet-ingestelde naam naar lege tekst. Een spelfout kan daardoor zonder directe foutmelding een leeg pad of een lege melding opleveren.
Een waarde zoals in count=5 slaat de tekst “5” op. Tekst naast een expansie toevoegen voert geen berekening uit: echo "$count+1" toont “5+1”. Bij rekenkundige expansie krijgen getallen een andere rol als berekeningen nodig zijn.
Lees een invoerregel
read -r -p "Your name: " name
echo "Hello, $name"
read slaat de ingevoerde regel op in name. -p geeft de prompt op en -r behoudt backslashes. Bij de invoer “Lee Kim” is de begroeting “Hello, Lee Kim”. Een script dat zonder aanwezige persoon draait, heeft invoer uit argumenten, bestanden of standaardwaarden nodig; een prompt kan een ontbrekende waarde niet betrouwbaar leveren.
Exporteer waarden voor kindprogramma's
Een gewone shellvariabele hoort bij de shell waarin die is ingesteld. Met exporteren markeer je de variabele voor opname in de omgeving die wordt gekopieerd naar programma's die die shell start:
export BACKUP_DIR=/mnt/usb
bash backup-notes.sh
Het Bash-kindproces kan nu BACKUP_DIR lezen. Als dat kindproces een andere waarde toekent, behoudt het ouderproces zijn eigen waarde. Overerving van de omgeving gaat van ouder naar kind; latere wijzigingen worden niet teruggestuurd.
| Naam | Gebruikelijke betekenis |
|---|---|
HOME | Homedirectory |
USER | Gebruikersnaam |
PWD | Huidige werkdirectory |
PATH | Directory's waarin naar commandonamen wordt gezocht |
env of printenv toont omgevingsvariabelen. unset name verwijdert de variabele met de naam name; het kent geen lege tekenreeks toe. Bij normale expansie kunnen beide leeg lijken, maar een controle op niet-ingestelde variabelen kan een ontbrekende variabele van een ingestelde onderscheiden.
Belangrijkste punten
- Toekenningen gebruiken
name=valuezonder spaties rond=. - Variabelenamen zijn hoofdlettergevoelig; gebruik namen met kleine letters voor je eigen waarden.
${name}markeert het einde van een variabelenaam vóór aansluitende tekst.read -rleest invoer en behoudt backslashes.- Geëxporteerde waarden worden naar kindprocessen gekopieerd, nooit terug naar een ouderproces.
unsetverwijdert een variabele.
2.2 Scherm woorden, variabelen en speciale tekens af
Bash leest een commando voordat het programma zijn argumenten ontvangt. Spaties scheiden woorden en tekens zoals *, ?, $, ;, &, |, < en > hebben speciale functies. Afscherming bepaalt welke van die functies actief blijven.
Kies wat mag expanderen
| Vorm | Wat Bash doet |
|---|---|
'fixed text' | Houdt alles ertussen letterlijk. |
"text with $name" | Behoudt spaties en jokertekens, maar expandeert variabelen, commando-uitvoer en rekenkundige expressies. |
\* | Behandelt het volgende teken buiten aanhalingstekens letterlijk. |
Vergelijk met HOME=/home/sam:
echo 'Home: $HOME *'
echo "Home: \$HOME *"
De eerste toont “Home: $HOME *”. De tweede toont “Home: /home/sam *”. Het sterretje blijft in beide gevallen letterlijk, maar alleen dubbele aanhalingstekens laten de variabele expanderen. Een enkel aanhalingsteken kan niet rechtstreeks binnen een tekenreeks tussen enkele aanhalingstekens worden geplaatst.
Binnen dubbele aanhalingstekens kunnen backslashes een dollarteken, backtick, dubbel aanhalingsteken of backslash afschermen. Zo toont echo "Price: \$5" de tekst “Price: $5”. Buiten aanhalingstekens toont echo 5 \* 3 de tekst “5 * 3” en maakt touch my\ file.txt één bestand met een spatie in de naam.
Volg een niet-afgeschermde waarde door Bash
file="my report.txt"
cp $file backup/
Eerst expandeert Bash de variabele. Daarna verdeelt woordsplitsing de waarde bij spaties, tabs en nieuweregeltekens. Het commando ontvangt my, report.txt en backup/ als afzonderlijke argumenten. Het probeert twee bronbestanden te kopiëren in plaats van het ene bedoelde bestand.
Als een resulterend woord jokertekens bevat, vervangt bestandsnaamexpansie het daarna door overeenkomende bestandsnamen. Een opgeslagen waarde van *.txt kan meerdere bestandsargumenten worden als die zonder aanhalingstekens wordt geëxpandeerd. Deze extra stappen vinden plaats voordat cp start; het programma kan je bedoelde groepering niet herstellen.
cp "$file" backup/
Nu blijft de geëxpandeerde waarde één argument, “my report.txt”. Bash verwijdert de aanhalingstekens zelf; het zijn instructies voor de verwerking, geen onderdeel van het pad dat aan cp wordt doorgegeven. Zet variabele-expansies en commandosubstituties tussen dubbele aanhalingstekens wanneer hun volledige waarde bij elkaar moet blijven.
Behoud een lege waarde
Afscherming is ook belangrijk als een waarde leeg is. In [ $answer = yes ] verdwijnt een lege answer, waardoor een ongeldige test overblijft. [ "$answer" = yes ] geeft een lege tekenreeks door als één argument, zodat de test geldig en onwaar is.
Dezelfde groeperingsregel geldt voor letterlijke woorden. mkdir new folder maakt twee directory's, terwijl mkdir "new folder" er één maakt. Een volledig pad afschermen is nuttig, of de spatie nu rechtstreeks is getypt of uit een variabele komt.
Combineer letterlijke en geëxpandeerde tekst
Aangrenzende afgeschermde delen zonder spatie ertussen vormen één woord. Met price=8 toont echo 'Price: $'"$price" de tekst “Price: $8”. Het vaste deel staat tussen enkele aanhalingstekens en het veranderlijke deel tussen dubbele. Ook een zoekpatroon kun je vast houden: grep 'cost: \$[0-9]' prices.txt geeft het patroon zonder shellexpansie door, zodat grep het patroon kan interpreteren.
Belangrijkste punten
- Enkele aanhalingstekens houden tekst letterlijk; dubbele aanhalingstekens staan expansies toe en houden waarden bij elkaar.
- Niet-afgeschermde expansies ondergaan eerst woordsplitsing en daarna bestandsnaamexpansie.
- Aanhalingstekens behouden een lege waarde als argument.
- Een backslash kan één speciaal teken letterlijk maken.
- Aangrenzende afgeschermde delen vormen één woord als er geen spatie tussen staat.
2.3 Vang commando-uitvoer op en reken met gehele getallen
Commando's leveren vaak een waarde op die een andere stap nodig heeft. Bash kan die uitvoer opvangen, in tekst plaatsen of in een berekening gebruiken. Commandosubstitutie en rekenkundige expansie gebruiken vergelijkbare leestekens, maar doen iets anders.
Vang standaarduitvoer op
today=$(date +%F)
cp notes.txt "notes-${today}.txt"
$(...) voert een commando uit en vervangt de substitutie door de standaarduitvoer ervan. Op 2026-10-22 bevat today “2026-10-22” en heet de kopie notes-2026-10-22.txt. Een datum in de volgorde jaar-maand-dag houdt bestandsnamen bij sortering op naam in datumvolgorde. Je kunt de substitutie ook rechtstreeks in de naam zetten: "notes-$(date +%F).txt".
Nieuweregeltekens aan het einde worden uit opgevangen uitvoer verwijderd. De oudere vorm met backticks vangt ook uitvoer op, maar $(...) is gemakkelijker te lezen en te nesten. Scherm een substitutie die als commandoargument wordt gebruikt af, zoals "$(date +%F)", om het resultaat bij elkaar te houden.
Commandosubstitutie vangt alleen standaarduitvoer op. Fouten die naar standaardfoutuitvoer worden gestuurd, gaan nog steeds naar hun gebruikelijke bestemming. result=$(some_command 2>&1) combineert beide stromen binnen de opgevangen uitvoer als het script dat nodig heeft. Als je fouten mengt met een waarde die een getal moet bevatten, mislukken latere berekeningen.
Vang een telling op zonder bestandsnaam
lines=$(wc -l < access.log)
echo "Lines: $lines"
Als het bestand 342 nieuweregeltekens bevat, levert wc de telling 342. Door het bestand naar wc om te leiden bevat de uitvoer alleen de telling; wc -l access.log toont ook de bestandsnaam. Een resultaat dat op een getal lijkt, kun je dan hergebruiken, mits het commando is geslaagd.
Reken met gehele getallen
$(( ... )) voert rekenkundige expansie uit:
echo "$(( 17 / 5 ))"
echo "$(( 17 % 5 ))"
De resultaten zijn 3 en 2. Bij geheeltallige deling vervalt de rest; % geeft die terug. Voor optellen, aftrekken en vermenigvuldigen gebruik je +, - en *. Variabelenamen kunnen binnen de expressie zonder dollarteken voorkomen: total=$(( price * qty )).
Met a=5 toont echo "$a+3" de tekst “5+3”. echo "$(( a + 3 ))" rekent en toont 8. De extra haakjes kiezen voor rekenkunde; $(a + 3) zou in plaats daarvan een commando met de naam a proberen uit te voeren.
Een teller begint met een waarde zoals count=0 en wordt bijgewerkt met count=$(( count + 1 )). Bash biedt ook (( count++ )); dit is een rekenkundig commando met een eigen afsluitstatus, wat belangrijk is in scripts die foutopties gebruiken.
Behoud de benodigde nauwkeurigheid
Bash rekent met gehele getallen. 7 / 2 geeft 3 en een decimale waarde zoals 2.5 veroorzaakt een rekenkundige syntaxisfout. Een afzonderlijke tool kan met decimalen rekenen:
echo "scale=2; 7 / 2" | bc
Dit levert 3.50 op. Vermenigvuldig bij het rekenen met gehele getallen vóór het delen als het product een breukdeel behoudt dat je nog nodig hebt. Voor 45 van de 60 geeft $(( 45 * 100 / 60 )) de waarde 75. Als je eerst deelt, geeft 45 / 60 nul, zodat $(( 45 / 60 * 100 )) nul blijft; het verloren breukdeel kun je niet herstellen door later te vermenigvuldigen.
Belangrijkste punten
$(command)vangt standaarduitvoer op en verwijdert nieuweregeltekens aan het einde.$((expression))rekent met gehele getallen.- Gebruik
/voor geheeltallige deling en%voor de rest ervan. - Een teller slaat zijn bijgewerkte waarde na elke verhoging op.
- Vermenigvuldigen vóór het delen kan vroegtijdig verlies van nauwkeurigheid bij gehele getallen voorkomen.
- Gebruik een tool zoals
bcals een decimaal resultaat nodig is.
3Geef met afsluitcodes aan of een commando is geslaagd of mislukt
Een script heeft een resultaat nodig dat zowel mensen als programma's kunnen begrijpen. Uitvoer op het scherm legt uit wat er is gebeurd, terwijl een afsluitstatus een ander commando laat bepalen of het verdergaat. Je slaat die status op, controleert afhankelijke stappen en houdt mislukkingen in pijplijnen zichtbaar. Syntaxiscontroles, uitvoeringstraceringen en foutopties helpen de oorzaak van een mislukte uitvoering te vinden voordat latere commando's de gevolgen moeilijker zichtbaar maken.
3.1 Lees afsluitcodes uit, stel ze in en koppel er vervolgcommando's aan
Een commando meldt zijn resultaat op twee manieren: het kan tekst tonen en het geeft een afsluitstatus terug. Programma's gebruiken die status om te bepalen wat er daarna gebeurt. Een script kan een geruststellende melding tonen en toch zijn mislukt, of niets tonen en slagen.
Lees een status voordat die verandert
Een afsluitstatus is een geheel getal van 0 tot en met 255. Nul betekent succes. Een waarde anders dan nul meldt een mislukking of een ander gedocumenteerd resultaat. grep gebruikt bijvoorbeeld 0 voor een overeenkomst, 1 voor geen overeenkomst en 2 voor een fout. Een zoekopdracht zonder overeenkomst kan voor je taak een normale uitkomst zijn, ook al is de status anders dan nul.
$? bevat de status van het meest recente commando:
grep -q root /etc/passwd
status=$?
echo "Search status: $status"
De toekenning slaat het resultaat op voordat een ander commando het vervangt. In ls /missing; echo $?; echo $? geeft GNU ls de waarde 2 terug voor het ontoegankelijke pad op de commandoregel. De eerste echo toont 2 en slaagt daarna. De tweede toont 0, de status van die echo, niet van de oorspronkelijke bestandslijst.
Eindig met een bruikbaar resultaat
exit 1 beëindigt een script onmiddellijk en meldt 1 aan de aanroeper. exit 0 meldt succes. Een exit zonder getal gebruikt de status van het vorige commando; als het script normaal het einde bereikt, gebruikt het de status van het laatste commando. Kies codes binnen 0–255: exit 256 loopt terug naar 0 en zou ten onrechte succes melden.
Sommige statussen komen van Bash zelf:
| Code | Betekenis |
|---|---|
| 127 | Het commando is niet gevonden. |
| 126 | Het commando is gevonden maar kon niet worden uitgevoerd. |
128 + n | Het commando is geëindigd door signaalnummer n. |
Ctrl+C verzendt signaal 2, dus een commando dat op die manier wordt beëindigd, meldt gewoonlijk 130. Gewone programma's documenteren ook hun eigen codes; 1 en 2 hebben niet één universele betekenis voor alle tools.
Koppel afhankelijke commando's
mkdir -p ~/backup && cp notes.txt ~/backup/
cd /data/reports || exit 1
&& voert het volgende commando alleen uit na succes. Hier hangt het kopiëren af van het maken of vinden van de back-updirectory. || voert het volgende commando alleen uit na mislukking. Hier stopt een mislukte directorywijziging het script voordat latere commando's de verkeerde werkdirectory gebruiken.
true geeft 0 terug; false geeft 1 terug. Een ! vooraan keert succes of mislukking van een commando om. ! grep -q ERROR app.log slaagt als de zoekopdracht geen overeenkomende regel vindt, maar ook als grep met een fout mislukt; gebruik expliciete statuscontroles als je die uitkomsten moet onderscheiden.
Controleer een hele pijplijn
grep ERROR missing.log | wc -l
Standaard heeft een pijplijn de status van het laatste commando. grep mislukt op het ontbrekende bestand, maar wc leest een lege stroom, toont 0 en slaagt. De status van de pijplijn is daarom 0.
set -o pipefail laat een pijplijn mislukken als een van de onderdelen mislukt. Het geeft de meest rechtse status anders dan nul terug, of 0 als alle commando's slagen. Daardoor worden fouten eerder in de pijplijn zichtbaar voor if, &&, || en de aanroeper. Een planner kan dan een geslaagd rapport onderscheiden van een rapport dat zijn invoer nooit heeft gelezen.
Belangrijkste punten
- Afsluitstatus 0 betekent succes; de betekenis van andere resultaten wordt door elk programma gedocumenteerd.
- Sla
$?onmiddellijk op als je die na een ander commando nodig hebt. exitgeeft een resultaat aan de aanroeper van het script.&&gaat verder na succes en||gaat verder na mislukking.- Zonder
pipefailmeldt een pijplijn alleen de status van het laatste commando.
3.2 Spoor fouten op en stop een script veilig
Bash gaat normaal gesproken verder nadat een commando is mislukt. Als het volgende commando van dat werk afhangt, kan doorgaan een kleine fout tot een groter probleem maken. Controleer afhankelijke stappen expliciet en gebruik daarna syntaxiscontroles en tracering om te achterhalen waarom een uitvoering anders verloopt dan je had bedacht.
Stop voordat een mislukte stap verdere gevolgen heeft
cd /backups || exit 1
Commando's daarna kunnen nu alleen worden uitgevoerd als de directorywijziging is geslaagd. Dit is belangrijk vóór bestandsbewerkingen: als een directorywijziging mislukt en het script doorgaat, verwijzen relatieve paden nog steeds naar de oude directory. Controleer de bestemming voordat je commando's uitvoert die bestanden wijzigen of verwijderen.
Een foutmelding en een status die mislukking aangeeft, zijn voor verschillende lezers bedoeld:
echo "Error: $file not found" >&2
exit 1
De melding gaat naar standaardfoutuitvoer, zodat standaarduitvoer beschikbaar blijft voor gegevens. Met ./report.sh > report.txt blijft de melding zichtbaar in de terminal terwijl de normale uitvoer in het bestand terechtkomt. Dankzij de status anders dan nul kan een ander programma de fout herkennen zonder de zin te lezen.
Controleer de syntaxis en traceer daarna de uitvoering
| Commando | Wat het doet |
|---|---|
bash -n script.sh | Leest de syntaxis zonder commando's uit te voeren. |
bash -x script.sh | Voert het script uit en toont geëxpandeerde commando's voordat ze worden uitgevoerd. |
Een ontbrekende fi, done of afsluitend aanhalingsteken is een syntaxisprobleem. bash -n kan het vinden, vaak via een melding “unexpected end of file”. Voor een syntactisch geldig bestandspad met een spelfout moet je de uitvoering controleren.
Bij tracering krijgen commando's een + als voorvoegsel. Een regel zoals cp "$src" "$dest" laat zien welke paden daadwerkelijk zijn doorgegeven. Met set -x en set +x schakel je tracering voor een gedeelte in en uit.
Begrijp de foutopties
set -euo pipefail combineert drie instellingen:
-estopt na een niet-afgehandelde mislukking van een commando.-umeldt een niet-ingestelde variabele als fout.pipefailzorgt ervoor dat mislukte onderdelen van een pijplijn de afsluitstatus van de pijplijn beïnvloeden.
-e laat ruimte voor verwachte mislukkingen in voorwaarden van if, while en until, ontkende commando's en commando's die niet de laatste zijn in lijsten met && of ||. Zonder pipefail leidt een mislukking vóór het laatste commando van een pijplijn niet tot stoppen. Expliciete controles blijven nuttig omdat ze aangeven wat het script moet doen als een bepaalde stap mislukt.
Een rekenkundig commando meldt ook waar of onwaar. (( count++ )) geeft status 1 terug als de oude waarde 0 is. Een niet-afgehandeld gebruik onder -e kan het script daardoor stoppen, ook al is de verhoging uitgevoerd. De toekenning count=$(( count + 1 )) vermijdt die status van het rekenkundige commando.
-u vangt een typefout zoals $filname op als alleen filename is ingesteld. Het wijst een variabele die bestaat maar leeg is niet af. ${dir:?not set} controleert bij die expansie of dir ontbreekt of leeg is. Een verwacht resultaat zonder overeenkomst kun je met een test afhandelen; command || true onderdrukt elke mislukking van dat commando, dus gebruik dit alleen als al die mislukkingen aanvaardbaar zijn.
Lees meldingen en ruim op
“Command not found” wijst op een probleem met een naam, een geïnstalleerd programma of PATH. “Permission denied” wijst op uitvoering of toegang tot een bestand. “Unary operator expected” komt vaak door een lege, niet-afgeschermde waarde in [ ]; “integer expression expected” betekent dat een numerieke test tekst heeft ontvangen.
Een EXIT-trap stelt een opruimactie in, zoals trap 'rm -f "$tmpfile"' EXIT, nadat aan tmpfile een waarde is toegekend. Het afgeschermde commando wordt uitgevoerd als Bash eindigt, ook bij een expliciete exit of een afsluiting na een fout onder -e. ShellCheck kan scripts vóór uitvoering ook controleren op veelvoorkomende fouten in afscherming en logica.
Belangrijkste punten
- Controleer een stap voordat je commando's uitvoert die ervan afhangen.
- Schrijf foutmeldingen naar standaardfoutuitvoer en meld mislukking met een status anders dan nul.
bash -ncontroleert de syntaxis;bash -xvoert uit en traceert.set -eheeft uitzonderingen voor geteste mislukkingen.set -uvangt niet-ingestelde variabelen op, terwijl${name:?message}ook lege waarden afwijst.- Een EXIT-trap kan een tijdelijk bestand verwijderen als het script eindigt.
4Neem beslissingen en herhaal taken
Een bruikbaar script kiest acties en herhaalt die voor wisselende invoer. Tests zetten vragen over bestanden, tekst en getallen om in succes of mislukking. Vertakkingen kiezen een actie, terwijl lussen commando's op lijsten toepassen of doorgaan totdat een voorwaarde verandert. Je volgt de waarde die bij elke doorgang wordt gebruikt en behoudt spaties, records en tellers terwijl gegevens door het script gaan.
4.1 Test bestanden, tekenreeksen en getallen
Een voorwaarde in Bash is een commando waarvan de status waar of onwaar betekent. Met tests stel je vragen over paden, tekst en getallen. Kies een operator die past bij het soort waarde; dezelfde zichtbare tekens kunnen als tekst en als getal verschillende betekenissen hebben.
Geef de test afzonderlijke woorden
test -f notes.txt en [ -f notes.txt ] vragen of een pad naar een bestaand gewoon bestand verwijst. [ is een commando en het laatste argument moet ] zijn. Spaties scheiden de argumenten:
[ -f "$file" ]
Zonder de spatie na [ kan Bash zoeken naar een commando met de naam [-f. In [ "$a"="$b" ] vormen de ontbrekende spaties rond = één niet-leeg woord, waardoor de test waar is, ook als de waarden verschillen. Operators moeten afzonderlijke argumenten zijn.
Kies een bestandstest
| Operator | Waar als het pad… |
|---|---|
-e | Bestaat. |
-f | Een bestaand gewoon bestand is. |
-d | Een bestaande directory is. |
-r, -w, -x | Leesbaar, schrijfbaar of uitvoerbaar is voor de huidige gebruiker. |
-s | Bestaat en groter is dan nul. |
-L | Een symbolische koppeling is. |
Voor een directory met de naam logs slagen -e en -d, terwijl -f mislukt. Bestandstests volgen een symbolische koppeling normaal gesproken naar het doel; -L controleert de koppeling zelf. Een verbroken koppeling kan daardoor aan -L voldoen en niet aan -e.
Vergelijk tekst of gehele getallen
Tekenreekstests gebruiken = en != voor gelijkheid en ongelijkheid. -z controleert op lengte nul en -n op een lengte anders dan nul. [ "$answer" = yes ] komt precies overeen met “yes”; “Yes” en “yes ” zijn andere tekst. Dubbele aanhalingstekens behouden een lege waarde in de test.
Vergelijkingen van gehele getallen gebruiken -eq, -ne, -lt, -le, -gt en -ge: gelijk, ongelijk, kleiner dan, kleiner dan of gelijk aan, groter dan en groter dan of gelijk aan. [ "$count" -gt 100 ] vraagt of het getal groter is dan 100.
[ 07 -eq 7 ]
[ 07 = 7 ]
De numerieke vergelijking slaagt omdat de waarden gelijk zijn. De tekenreeksvergelijking mislukt omdat één tekst met een extra nul begint.
Gebruik geen losse > voor een numerieke test binnen [ ]. In [ 10 > 9 ] leidt Bash uitvoer om naar een bestand met de naam 9 en test het overblijvende niet-lege woord. In Bash vergelijkt de operator in [[ 10 < 9 ]] tekenreeksen, zodat het eerste teken 1 vóór 9 wordt gesorteerd. Gebruik -lt of -gt voor numerieke vergelijkingen, of Bash-rekenkunde zoals (( count > 100 )).
Combineer voorwaarden
[ ! -d "$dir" ] slaagt als het pad geen bestaande directory is; het kan een gewoon bestand zijn of ontbreken. [ -f "$f" ] && [ -r "$f" ] slaagt alleen als beide tests slagen. Afzonderlijke tests die met || zijn verbonden, slagen als er minstens één slaagt.
Bash heeft ook het sleutelwoord voor een testconstructie [[ ... ]]. Het voorkomt woordsplitsing van de variabele-expansies en staat && en || binnen de test toe. Een niet-afgeschermd patroon rechts van == wordt als patroon vergeleken: [[ $file == *.log ]] komt overeen met “app.log”. Als je dat patroon afschermt, wordt het letterlijk. Deze syntaxis vereist Bash; dash ondersteunt die niet.
Belangrijkste punten
- Een test meldt waar met status 0 en onwaar met status 1.
- Zet spaties rond
[en de operators en sluit af met]. - Bestandstests maken onderscheid tussen bestaan, type en toegang.
- Tekenreeksgelijkheid vergelijkt tekst; numerieke operators vergelijken gehele getallen.
- Gebruik
-gten-ltvoor getallen, geen losse omleidingstekens. - Negatie keert een test om;
&&vereist beide voorwaarden. - Bash
[[ ... ]]ondersteunt patronen en voorkomt woordsplitsing.
4.2 Kies acties met if, elif, else en case
Voorwaarden worden nuttig als ze acties kiezen. Een if-blok kiest een vertakking op basis van commandoresultaten. Een case-blok kiest een vertakking door één waarde met patronen te vergelijken. Beide maken de beschikbare acties zichtbaar in het script.
Laat een commando een vertakking kiezen
if grep -q ERROR app.log; then
echo "Errors found"
else
echo "No successful match"
fi
if voert het commando uit en gaat de eerste vertakking in als het 0 teruggeeft. Anders gaat het naar else. De zoekopdracht zelf is de voorwaarde; het is niet nodig die uit te voeren, iets te tonen en daarna $? te bekijken. Een fout van grep geeft ook een waarde anders dan nul, dus dit voorbeeld beschrijft de else-vertakking als een zoekopdracht zonder succesvolle overeenkomst, niet als bewijs dat het bestand geen fouten bevat.
then moet een nieuw commando beginnen: zet het op de volgende regel of na een puntkomma. fi sluit het blok af. Een ontbrekende fi veroorzaakt vaak een syntaxisfout bij het bestandseinde omdat Bash nog wacht op de afsluiting van het blok.
Orden overlappende voorwaarden
elif voegt een test toe die alleen wordt uitgevoerd als eerdere tests zijn mislukt. Voor een schijfgebruikspercentage als geheel getal:
if [ "$usage" -ge 90 ]; then
echo "CRITICAL: disk ${usage}% full"
elif [ "$usage" -ge 75 ]; then
echo "WARNING: disk ${usage}% full"
else
echo "OK: disk ${usage}% full"
fi
Met usage=82 mislukt de eerste test en slaagt de tweede, wat “WARNING: disk 82% full” oplevert. Bij 95 wordt de eerste vertakking uitgevoerd en de waarschuwingsvertakking overgeslagen. Als de test op 75 eerst kwam, zou 95 daaraan voldoen en nooit de test voor kritiek bereiken. Orden overlappende bereiken zo dat de strengere voorwaarde aan bod komt.
Alleen de eerste vertakking waarvan de test slaagt, wordt uitgevoerd. else heeft geen voorwaarde nodig en verwerkt wat overblijft. Je kunt elif of else weglaten als de taak die niet nodig heeft.
Vergelijk één waarde met case
case "$1" in
start) echo "Starting" ;;
stop) echo "Stopping" ;;
y|Y|yes) echo "Confirmed" ;;
*) echo "Usage: $0 start|stop|y|Y|yes" >&2; exit 2 ;;
esac
Elk patroon eindigt met ), elke vertakking met ;; en esac sluit het blok af. De | binnen een patroon geeft alternatieven. De laatste * is het allesomvattende patroon en hoort als laatste omdat het met elke waarde overeenkomt.
case gebruikt bestandsnaampatronen, geen reguliere expressies. *.jpg komt overeen met een waarde die eindigt op .jpg. [0-9]* komt overeen met een waarde waarvan het eerste teken een cijfer is; de * kan daarna met elke volgende tekst overeenkomen, dus het patroon komt ook overeen met “7draft”. Het bewijst niet dat een hele waarde alleen cijfers bevat.
Kies de passende structuur
Gebruik case als één invoer, zoals een subcommando of antwoord, meerdere benoemde vormen heeft. Gebruik if als voorwaarden verschillende zaken onderzoeken, zoals of een bestand bestaat en of een aantal een grens overschrijdt. Een patroonvergelijking gaat over de tekens in een waarde; een bestandstest gaat over het pad op schijf. Een naam die eindigt op .log kan met een patroon overeenkomen, ook als zo'n bestand niet bestaat.
Belangrijkste punten
ifkiest een vertakking op basis van de afsluitstatus van een commando; elk commando kan een voorwaarde zijn.elif-tests worden alleen uitgevoerd nadat eerdere voorwaarden zijn mislukt.- Orden overlappende grenswaarden van de strengere naar de ruimere.
casekiest het eerste overeenkomende patroon en gebruikt;;om elke vertakking af te sluiten.- Een patroonovereenkomst bewijst niet dat een bestand bestaat.
4.3 Herhaal commando's voor lijsten en bestanden met for
Een for-lus geeft dezelfde reeks commando's bij elke doorgang een nieuwe waarde. De lijst kan letterlijke woorden, overeenkomende bestandsnamen, een getallenbereik of de argumenten van het script bevatten. Bash kent één lijstitem toe aan de lusvariabele voordat het luslichaam wordt uitgevoerd.
Doorloop een vaste lijst
for host in web1 web2 db1; do
echo "Checking $host"
done
De eerste doorgang heeft host=web1, de tweede host=web2 en de derde host=db1. De lus toont drie regels. do opent het luslichaam en done sluit het af. De variabele blijft na de lus beschikbaar en bevat de laatst toegekende waarde.
Een lus kan ook een resultaat opbouwen:
total=0
for n in 4 8 15; do
total=$(( total + n ))
done
echo "$total"
Het opgeslagen totaal verandert van 0 naar 4, dan 12 en dan 27. Initialiseer het totaal vóór de lus zodat de eerste optelling een vastgelegde beginwaarde heeft.
Doorloop overeenkomende bestanden
for f in *.log; do
[ -f "$f" ] || continue
gzip -- "$f"
done
Bash expandeert het bestandsnaampatroon naar overeenkomende namen voordat het luslichaam wordt uitgevoerd. Elke overeenkomende bestandsnaam blijft één lijstitem, ook als die spaties bevat. Door "$f" binnen het luslichaam af te schermen, blijft dat item bij elkaar wanneer het aan gzip wordt doorgegeven. De test op een gewoon bestand slaat hier ook directory's over waarvan de naam eindigt op .log.
Met de standaardinstellingen voor bestandsnaamexpansie van Bash blijft een *.log zonder overeenkomsten letterlijk staan. Een lus zonder controle zou één keer worden uitgevoerd op de tekens *.log en het commando zou mislukken. [ -e "$f" ] || continue slaat niet-bestaande paden over; gebruik -f als je alleen gewone bestanden wilt.
Maak geen bestandsnamenlus op basis van $(ls). De uitvoer is tekst, dus woordsplitsing kan “my report.txt” in twee lijstitems veranderen. Een bestandsnaampatroon levert de bestandsnamen al met hun grenzen intact.
Maak van elke oude naam een nieuwe
for f in *.jpeg; do
[ -f "$f" ] || continue
mv -- "$f" "${f%.jpeg}.jpg"
done
${f%.jpeg} verwijdert het achtervoegsel .jpeg uit de waarde. Voor “beach day.jpeg” wordt de bestemming “beach day.jpg”. De twee afgeschermde argumenten houden beide paden intact. -- geeft mv aan dat volgende argumenten namen zijn, ook als er één met - begint. Gebruik bij het uitproberen van het voorbeeld een bestemmingsmap zonder conflicterende namen, omdat mv een bestaande bestemming kan vervangen.
Tel door een bereik
for i in {1..5} levert 1 tot en met 5. Bash expandeert de accolades voordat het variabelen expandeert, dus {1..$n} levert geen bereik met variabele lengte op. Gebruik voor een opgeslagen grens de rekenkundige vorm:
for (( i = 1; i <= n; i++ )); do
echo "$i"
done
De eerste expressie initialiseert de teller, de middelste test die vóór elke doorgang en de laatste werkt die bij. for i in $(seq 1 "$n") levert ook een getallenlijst voor een geschikte positieve gehele grenswaarde. De bewust niet-afgeschermde substitutie levert hier afzonderlijke getallen.
Voor argumenten levert for arg in "$@" één item per oorspronkelijk argument. De kortere vorm for arg; do betekent hetzelfde, inclusief het behoud van spaties binnen elk argument.
Belangrijkste punten
- Een
for-lus voert het luslichaam één keer per lijstitem uit. - Bestandsnaampatronen leveren volledige bestandsnamen; scherm de lusvariabele in het luslichaam af.
- Een bestandsnaampatroon zonder overeenkomsten blijft bij de standaardinstellingen van Bash letterlijk staan, dus controleer bestandslussen.
- Vermijd bestandsnamenlussen die zijn opgebouwd uit
$(ls). - Bereiken tussen accolades staan vast vóór variabele-expansie; gebruik een rekenkundige lus voor een variabele grens.
"$@"behoudt de oorspronkelijke grenzen tussen argumenten.
4.4 Herhaal commando's totdat een voorwaarde verandert met while en until
Sommige herhalingen eindigen wanneer een voorwaarde verandert, niet wanneer een lijst opraakt. while en until testen vóór elke doorgang. Het luslichaam van while wordt uitgevoerd zolang de voorwaarde slaagt; dat van until zolang de voorwaarde mislukt. Beide lussen kunnen nul keer worden uitgevoerd.
Werk bij waarvan de voorwaarde afhangt
i=1
while [ "$i" -le 3 ]; do
echo "Attempt $i"
i=$(( i + 1 ))
done
De voorwaarde ziet eerst 1, dan 2 en dan 3. Het luslichaam toont die drie pogingnummers en verhoogt telkens de teller. Na de wijziging naar 4 mislukt de volgende test en eindigt de lus. Als de wijziging ontbrak, zou i op 1 blijven en zou de lus doorgaan. Ctrl+C stopt een actieve voorgrondlus.
Om op een bestand te wachten:
until [ -f /tmp/export.done ]; do
sleep 5
done
Als het bestand al bestaat, wordt het luslichaam nooit uitgevoerd. Anders pauzeert sleep 5 vijf seconden vóór de volgende controle. Een pauze voorkomt dat de lus voortdurend test en processortijd verspilt.
Lees records als regels
while IFS= read -r line; do
echo "Host: $line"
done < hosts.txt
read levert bij elke doorgang één regel en geeft bij het bestandseinde een status terug die mislukking aangeeft. IFS= behoudt spaties aan het begin en einde van de regel; -r behoudt backslashes. De invoeromleiding na done voert invoer toe aan de hele lus, niet alleen aan het laatste commando.
Een regel zoals “web1 production” blijft één waarde. for line in $(cat hosts.txt) zou splitsen bij spaties, tabs en nieuweregeltekens en die twee woorden als afzonderlijke iteraties behandelen. Die vorm kan willekeurige records per regel niet behouden.
Behoud wijzigingen na de lus
Een pipe naar een lus, zoals cat hosts.txt | while read -r line; do ...; done, voert de lus in Bash normaal gesproken uit in een kindproces. Een teller die daar wordt gewijzigd, gaat voor het ouderproces verloren als het kindproces eindigt. Leid het bestand om naar de lus als latere commando's de opgebouwde waarden nodig hebben:
count=0
while IFS= read -r line; do
count=$(( count + 1 ))
done < hosts.txt
echo "$count"
Dit verwerkt regels die eindigen op een nieuweregelteken en behoudt de bijgewerkte telling in de huidige shell. Er is geen pijplijn die een kindproces voor de lus maakt.
Verwerk het laatste record en voortijdige beëindiging
Een bestand kan eindigen met tekst maar zonder afsluitend nieuweregelteken. read slaat die laatste tekst op maar meldt mislukking, zodat een gewone while read het luslichaam voor dat record niet ingaat. Voeg een tweede test toe om de opgeslagen niet-lege tekst te accepteren:
while IFS= read -r line || [ -n "$line" ]; do
echo "Host: $line"
done < hosts.txt
break verlaat de lus onmiddellijk. continue slaat de overige commando's in de huidige doorgang over en gaat daarna terug naar de volgende controle van de voorwaarde. Een while true-lus heeft daarom een break, een exit of een signaal nodig om te eindigen; die kan een menu ondersteunen dat stopt als de invoer “q” is. Plaats in een tellerlus een wijziging vóór elke continue die die wijziging anders zou overslaan, anders kan die doorgang zich eindeloos herhalen.
Belangrijkste punten
whileherhaalt na succes;untilherhaalt na mislukking.- Beide lussen testen voordat ze hun luslichaam ingaan.
- Werk een teller bij of pauzeer een lus die herhaaldelijk controleert, zodat die voortgang maakt zonder voortdurend te wachten en te controleren.
IFS= read -rbehoudt spaties en backslashes in invoer per regel.- Leid een bestand om naar de lus om gewijzigde variabelen in de huidige shell te behouden.
- Een extra test op een niet-lege tekenreeks behoudt een laatste record zonder nieuweregelteken.
breakverlaat een lus;continueslaat over naar de volgende doorgang.
5Geef argumenten door aan scripts
Met commandoregelargumenten kan één script veel taken uitvoeren zonder de code te bewerken. Je leest afzonderlijke waarden, behoudt een volledige argumentenlijst en verwerkt opties vooraan. Voordat het werk begint, tel en controleer je de invoer, leg je een correcte aanroep uit en geef je standaardwaarden voor optionele waarden op. Het resultaat kan vanaf een prompt of zonder toezicht worden uitgevoerd, met duidelijke meldingen en een afsluitstatus als de invoer onbruikbaar is.
5.1 Lees positionele parameters en het aantal argumenten uit
Argumenten maken van een script met vaste invoer een herbruikbaar commando. Bash plaatst de woorden na de scriptnaam in positionele parameters. Hun grenzen worden bepaald door de aanroepende shell, dus aanhalingstekens zijn belangrijk bij zowel de aanroep van het script als het gebruik van die waarden.
Herken de parameters
./backup.sh /home/sam/docs /mnt/usb
Binnen het script is $0 gelijk aan ./backup.sh, $1 aan /home/sam/docs en $2 aan /mnt/usb. $# is 2, het aantal argumenten. Het script kan cp -r "$1" "$2" gebruiken om de bronmap naar de bestemming te kopiëren zonder een van beide paden vast in de code te zetten.
$0 geeft de naam aan waarmee het script is gestart; die telt niet mee in $#. Bij ./greet.sh Ana "Lee Kim" is het eerste argument “Ana” en het tweede “Lee Kim”. Zonder de aanhalingstekens rond de tweede naam zou het script drie argumenten ontvangen.
Gebruik accolades na het negende argument
$1 tot en met $9 duiden de eerste negen positionele parameters aan. De tiende vereist ${10} en latere posities volgen dezelfde vorm. $10 betekent de expansie van $1 gevolgd door het letterlijke teken 0. Als het eerste argument “Ana” is, wordt $10 gelijk aan “Ana0”, ook als er een tiende argument bestaat.
Een weggelaten parameter expandeert onder normale instellingen naar lege tekst. Bij twee argumenten ontbreekt $3; onder set -u veroorzaakt expansie ervan een fout voor een niet-ingestelde variabele. Controleer het aantal voordat je verplichte posities leest, of gebruik een expansie die een standaardwaarde levert.
Behoud alle grenzen tussen argumenten
Stel dat een script "a b" en c ontvangt. Vergelijk:
| Expansie | Doorgegeven woorden |
|---|---|
"$@" | Twee: “a b” en “c”. |
"$*" | Eén: “a b c”, met de gebruikelijke spatie als scheidingsteken. |
$@ | Drie: “a”, “b” en “c” bij normale splitsing. |
"$@" is de gebruikelijke keuze om argumenten door te geven:
for arg in "$@"; do
echo "Argument: $arg"
done
De lus wordt bij die aanroep twee keer uitgevoerd, één keer per oorspronkelijk argument. Zonder argumenten draait de lus nul keer. Dubbele aanhalingstekens rond "$@" hebben een speciale betekenis: elke positionele parameter blijft een afzonderlijk woord, dus de aanhalingstekens voegen niet de hele lijst samen tot één woord.
"$*" voegt waarden samen met het eerste teken van IFS, normaal gesproken een spatie. Dat kan nuttig zijn voor één tekenreeks om te tonen, maar het verliest de afzonderlijke grenzen die een later commando nodig kan hebben.
Verwerk parameters met shift
shift verwijdert de eerste positionele parameter, schuift de latere op en verlaagt $#. Bij de back-upaanroep zorgt één shift ervoor dat $1 gelijk wordt aan /mnt/usb en het aantal aan 1. shift 2 verwijdert de eerste twee parameters tegelijk.
Dit maakt een lus mogelijk die $1 bekijkt, verwerkt en daarna doorschuift vóór de volgende doorgang. Test met [ "$#" -gt 0 ] of er argumenten over zijn; anders kan het script een ontbrekende waarde lezen of proberen verder te schuiven dan de beschikbare argumenten. Doorschuiven verandert $0 niet en kan de argumentenlijst van de oudershell die het script startte niet wijzigen.
Belangrijkste punten
$0is de aanroepnaam, terwijl$1en volgende de argumenten bevatten.$#telt argumenten, waarbij afgeschermde spaties binnen één argument blijven.- Gebruik
${10}voor het tiende argument;$10is$1gevolgd door0. "$@"behoudt argumenten afzonderlijk, terwijl"$*"ze samenvoegt.shiftverwijdert voorste parameters en verandert de overige posities.
5.2 Controleer argumenten, toon een gebruiksinstructie en stel standaardwaarden in
Een script moet vaststellen of zijn invoer bruikbaar is voordat het aan het werk gaat. Controleer het aantal argumenten en controleer daarna hun betekenis. Optionele invoer kan standaardwaarden hebben; ontbrekende verplichte invoer vereist een duidelijke foutmelding en een afsluitstatus anders dan nul.
Leg de verwachte aanroep uit
if [ "$#" -ne 2 ]; then
echo "Usage: $0 SOURCE DEST" >&2
exit 2
fi
Dit controleert het aantal voordat $1 of $2 wordt geëxpandeerd, dus het werkt ook onder set -u. De gebruiksinstructie gaat naar standaardfoutuitvoer. Hoofdletters duiden waarden aan die de gebruiker opgeeft, [DEST] zou een optionele bestemming betekenen en FILE... betekent één of meer bestandsargumenten. Een hulpoptie zoals -h toont normaal gesproken de gebruiksinstructie en sluit af met 0, omdat hulp vragen geslaagd gebruik is.
Alleen het aantal argumenten kan niet aangeven of een bron bruikbaar is. [ -d "$1" ] controleert op een bestaande directory. Een test op een gewoon bestand kan bestanden selecteren, maar het resultaat van de bewerking zelf moet nog steeds worden gecontroleerd: rechten of andere fouten kunnen lezen verhinderen.
Gebruik een standaardwaarde of vereis een waarde
logdir=${1:-/var/log}
src=${1:?Usage: backup.sh SOURCE [DEST]}
De eerste vorm gebruikt /var/log als de eerste parameter ontbreekt of leeg is. De tweede stopt een niet-interactief script in beide gevallen en toont de melding op standaardfoutuitvoer. De dubbele punt is onderdeel van beide vormen. Een standaardwaarde is een waarde die voor deze expansie wordt gebruikt; ${1:-...} voegt geen argument toe aan de lijst met positionele parameters.
Houd gedeeltelijke mislukking bij
Een script dat bestanden telt, kan na ongeldige invoer doorgaan en toch melden dat de hele taak niet is voltooid:
#!/bin/bash
if [ "$#" -eq 0 ]; then
echo "Usage: $0 FILE..." >&2
exit 2
fi
status=0
for f in "$@"; do
if [ -f "$f" ]; then
if lines=$(wc -l < "$f"); then
echo "$f: $lines lines"
else
echo "$f: could not count lines" >&2
status=1
fi
else
echo "$f: not a regular file" >&2
status=1
fi
done
exit "$status"
Voor notes.txt missing.txt toont het script de telling van het leesbare bestand en meldt het het ontbrekende bestand, waarna het afsluit met 1. De toekenning wordt rechtstreeks getest, zodat een leesfout geen geslaagde lege telling wordt. Later succes zet de opgeslagen foutvlag nooit terug op 0.
Verwerk eenvoudige opties vóór bestandsnamen
verbose=0
while [ "$#" -gt 0 ]; do
case "$1" in
-v) verbose=1; shift ;;
-h) echo "Usage: $0 [-v] FILE..."; exit 0 ;;
--) shift; break ;;
-*) echo "Unknown option: $1" >&2; exit 2 ;;
*) break ;;
esac
done
Elke herkende optie wordt met shift verwerkt en verwijderd. Het eerste gewone argument beëindigt de optieverwerking; -- beëindigt die ook en wordt zelf verwijderd. De resterende "$@" bevat de bestandsnamen, inclusief een naam die na -- met - begint. Bash getopts ondersteunt uitgebreidere verwerking van korte opties.
Een script zonder toezicht heeft alle verplichte invoer nodig uit argumenten, standaardwaarden of configuratie. read kan blijven wachten op een terminal of onmiddellijk mislukken bij het bestandseinde. Als je een ontbrekend argument door een prompt vervangt, heeft een geplande taak geen betrouwbare manier om verder te gaan.
Belangrijkste punten
- Controleer het aantal voordat je verplichte argumenten expandeert.
- Een gebruiksinstructie noemt verplichte, optionele en herhaalbare invoer.
${1:-value}levert een standaardwaarde;${1:?message}wijst een ontbrekende of lege waarde af.- Controleer het resultaat van de bewerking ook nadat je het bestandstype van de invoer hebt gecontroleerd.
- Behoud een algemene status die mislukking aangeeft als je doorgaat met meerdere invoerwaarden.
- Verwerk opties met
shiften behandel--als het einde van de opties.
6Plan scripts zodat ze automatisch worden uitgevoerd
Een script dat zonder toezicht draait, heeft een planning nodig en een manier om de resultaten te bekijken. Cron geeft overeenkomende kloktijden weer in één regel; systemd koppelt een service aan een timer. Je leert beide vormen lezen, zorgt voor de omgeving die de taak nodig heeft en houdt de uitvoer beschikbaar. Door de volgende activering en het laatste taakresultaat afzonderlijk te controleren, onderscheid je een actieve planning van werk dat daadwerkelijk is geslaagd.
6.1 Plan taken met cron
Cron start commando's op overeenkomende kloktijden. De crontab van elke gebruiker bewaart diens planning en taken worden als die gebruiker uitgevoerd. Een gepland script heeft zowel een correcte tijdexpressie nodig als een omgeving die de paden, invoer en uitvoerbestemming biedt.
Lees de vijf velden
Gebruik crontab -e om je tabel te bewerken en crontab -l om die te bekijken. crontab -r verwijdert de hele tabel zonder te vragen; gebruik de editor om één taak te verwijderen.
| Veld, op volgorde | Waarden |
|---|---|
| Minuut | 0–59 |
| Uur | 0–23 |
| Dag van de maand | 1–31 |
| Maand | 1–12 |
| Dag van de week | 0–7; 0 en 7 betekenen zondag |
30 2 * * * /home/sam/bin/backup.sh
Dit wordt elke dag om 02.30 uur uitgevoerd. Sterretjes accepteren elke waarde in een veld. 0 9 * * 1-5 kiest 09.00 uur op werkdagen en 0 0 1 * * kiest middernacht op de eerste dag van elke maand. Tijden gebruiken de tijdzone van het systeem, tenzij de cron-configuratie een andere ondersteunde tijdzone opgeeft.
Combineer bereiken, lijsten en stapgroottes
Een komma somt waarden op: 1,15 in het veld voor de dag van de maand kiest de eerste en de vijftiende. Een koppelteken geeft een bereik en / leidt een stapgrootte in. */15 in het minutenveld kiest 0, 15, 30 en 45.
*/20 8-10 * * * kiest drie minuten in elk van drie uren: negen dagelijkse uitvoeringen, beginnend om 08.00 uur en eindigend om 10.40 uur. Stapgroottes beginnen opnieuw binnen hun veld. */45 wordt uitgevoerd op minuut 0 en minuut 45 van elk uur; de tussenpoos tot minuut 0 van het volgende uur is slechts 15 minuten.
Als zowel de dag van de maand als de dag van de week is beperkt, is een overeenkomst met een van beide voldoende. 0 12 13 * 5 kiest het middaguur op de 13e en op vrijdagen, niet alleen op vrijdag de 13e. De andere velden moeten nog steeds overeenkomen.
Speciale tekenreeksen vervangen alle vijf velden: @hourly, @daily, @weekly, @monthly, @yearly en @reboot. @daily betekent middernacht, terwijl @reboot eenmaal bij het opstarten wordt uitgevoerd.
Geef paden op en bewaar de uitvoer
Cron gebruikt normaal gesproken /bin/sh voor de commandoregel, een korte PATH en geen opstartinstellingen van een interactieve shell. De eigen Bash-shebang van een uitvoerbaar script kiest nog steeds Bash. Gebruik absolute paden voor het script en de bestanden ervan, of stel PATH bovenaan de crontab in.
30 2 * * * /home/sam/bin/backup.sh >> /home/sam/backup.log 2>&1
De taak voegt beide uitvoerstromen achteraan toe aan het logbestand. Zonder omleiding verstuurt cron uitvoer per e-mail als e-mail is geconfigureerd, ook via MAILTO; anders kan uitvoer verloren gaan. Een procentteken heeft een speciale rol in een crontab-commando: het begint een nieuwe regel en de daaropvolgende invoer. Scherm een datumformaat daar af met een backslash, zoals in date +\%F. Een datumcommando binnen een afzonderlijk script gebruikt de gewone vorm %F.
Maak onderscheid tussen systeemplanningen en inhaaltaken
/etc/crontab en bestanden in /etc/cron.d/ voegen na de vijf tijdvelden een gebruikersveld toe. Zo wordt 30 2 * * * root /usr/local/bin/backup.sh als root uitgevoerd. Voeg dat gebruikersveld niet toe aan een persoonlijke crontab.
Veel distributies voeren ook geschikte uitvoerbare bestanden uit in /etc/cron.daily/, /etc/cron.weekly/ en /etc/cron.monthly/. De standaardnaamgevingsregels van Debian voor run-parts slaan namen met punten over, dus gebruik daar backup-notes, niet backup-notes.sh. Cron mist tijdstippen die verstrijken terwijl de computer uitstaat. Anacron kan periodieke dagelijkse, wekelijkse of maandelijkse taken na het opstarten inhalen.
Belangrijkste punten
- Een persoonlijke crontab heeft vijf tijdvelden die direct door een commando worden gevolgd.
- Lijsten, bereiken en stapgroottes selecteren waarden binnen elk veld.
- Bij beperkte velden voor dag van de maand en dag van de week is een overeenkomst met een van beide voldoende.
- Gebruik absolute paden en een uitvoerlogbestand voor taken zonder toezicht.
- Scherm
%in een crontab-commando af met een backslash, ook in datumformaten. - Systeemcrontabs voegen een gebruikersveld toe; voor periodieke mappen gelden ook regels voor welke bestanden geschikt zijn.
- Cron mist uitvoeringen terwijl de machine uitstaat; anacron ondersteunt het inhalen van periodieke taken.
6.2 Plan taken met systemd-timers
Systemd scheidt het werk van de planning. Een service-unit beschrijft het uit te voeren commando. Een timerunit beschrijft wanneer het moet starten. Standaard activeert backup.timer de unit backup.service, waarbij de gedeelde basisnaam het paar verbindt.
Schrijf de service en de kalenderplanning
Plaats deze systeemunits in /etc/systemd/system/:
# backup.service
[Unit]
Description=Nightly backup
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
Type=oneshot is geschikt voor een script dat één keer wordt uitgevoerd en eindigt. Gebruik een absoluut commandopad en maak het script uitvoerbaar met een Bash-shebang. De timer levert de planning:
# backup.timer
[Unit]
Description=Run backup.service daily at 02:30
[Timer]
OnCalendar=*-*-* 02:30:00
Persistent=true
[Install]
WantedBy=timers.target
OnCalendar vergelijkt datums en kloktijden. Hier accepteert de datum met jokertekens elke dag. Persistent=true maakt inhalen mogelijk nadat de timer inactief was: als minstens één kalenderuitvoering is gemist, start de timer de service eenmaal bij heractivering. Niet elke gemiste uitvoering wordt opnieuw uitgevoerd.
Laad en activeer de timer
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
Herlaad na het maken of wijzigen van unitbestanden. enable --now start de timer onmiddellijk en schakelt die in voor toekomstige systeemstarts. Alleen de service inschakelen maakt geen planning. Test het werk afzonderlijk met sudo systemctl start backup.service.
Kies kloktijd of verstreken tijd
| Instelling | Planning |
|---|---|
OnCalendar=Mon..Fri *-*-* 09:00:00 | Werkdagen om 09.00 uur |
OnCalendar=*:0/15 | Minuut 0, 15, 30 en 45 van elk uur |
OnBootSec=10min | Tien minuten na het opstarten |
OnUnitActiveSec=1h | Eén uur nadat de service voor het laatst is geactiveerd |
Kalenderexpressies kunnen daily gebruiken voor elke dag om middernacht of weekly voor maandag om middernacht. Controleer een expressie met systemd-analyze calendar "Mon..Fri 09:00" om de interpretatie en het volgende tijdstip te zien.
De laatste twee instellingen zijn monotone timers: ze meten de verstreken tijd vanaf een gebeurtenis. Combineer ze voor een eerste uitvoering na het opstarten en latere activeringen per uur. Persistent=true geldt voor kalendertimers; het voegt geen inhaalfunctie voor kalendertaken toe aan monotone timers.
Bekijk planning en resultaten afzonderlijk
systemctl list-timers toont de volgende en laatste activeringen. systemctl status backup.service toont het resultaat van de service en journalctl -u backup.service toont de uitvoer en fouten. Een vermelde volgende uitvoering toont aan dat een planning actief is, niet dat de vorige taak van het script is geslaagd.
Timers hebben een tijdvenster waarbinnen ze afgaan. AccuracySec staat standaard op één minuut; AccuracySec=1s verkleint het venster waarin uitvoeringen worden samengevoegd. RandomizedDelaySec voegt bewust een willekeurige vertraging toe om werk over machines te spreiden. Deze instellingen garanderen bij belasting geen exacte startseconde.
Voer een eigen gebruikerstimer uit
Gebruikersunitbestanden staan in ~/.config/systemd/user/ en commando's gebruiken systemctl --user, waaronder daemon-reload, enable --now en list-timers. Een gebruikersbeheerder draait normaal gesproken tijdens de sessie van die gebruiker. Een beheerder kan met loginctl enable-linger username gebruikersbeheer zonder aanmeldsessie inschakelen om het beschikbaar te houden zonder aanmelding.
Cron heeft een compacte tijdregel nodig en werkt zonder systemd. Timers voegen een serviceresultaat en logboek, het inhalen van kalendertaken en meer controle toe. Geen van beide laadt normaal gesproken ~/.bashrc; beide hebben scripts nodig die werken met expliciete paden en zonder interactieve prompts.
Belangrijkste punten
- De service zegt wat moet worden uitgevoerd; de timer zegt wanneer.
- Herlaad gewijzigde units en schakel de
.timerin met--now. - Kalendertimers volgen de kloktijd; monotone timers meten vanaf gebeurtenissen.
Persistent=truehaalt gemiste kalendertaken eenmaal in bij heractivering.- Controleer zowel de volgende activering van de timer als de status en het logboek van de service.
- Gebruikerstimers hebben een actieve gebruikersbeheerder nodig, met gebruikersbeheer zonder aanmeldsessie voor uitvoeringen zonder sessie.
Shellscripts: voorbeelden
1Sla een herhaalbaar mapoverzicht op
9 stappen
- 1IntroductieGeef een terugkerende taak één plek
Je controleert vaak waar je bent, toont de inhoud van een map en geeft een melding dat de taak is voltooid. Door de commando's op te slaan kun je ze in dezelfde volgorde herhalen.
Een script is een bestand met platte tekst dat door een interpreter wordt gelezen. Je maakt een klein overzicht, kiest expliciet Bash en voert het uit in een kindshell. De naam, het uitvoerrecht en de locatie van het bestand beantwoorden elk een andere vraag over het starten ervan.
- 2VoorbeeldSchrijf de commando's op volgorde
Sla dit als
folder-report.shop in een editor voor platte tekst:#!/bin/bash pwd ls echo "Report finished"De shebang kiest Bash als het bestand direct wordt uitgevoerd. Het commentaar legt de taak uit maar wordt niet uitgevoerd. Daarna voert Bash
pwd,lsenechoin die volgorde uit. De extensie.shhelpt een lezer het bestand te herkennen; die kiest niet de interpreter. - 3UitdagingControleer wat de taal kiest
Een collega verandert de eerste regel in
#!/bin/shen voegt later[[ ... ]]toe. Het bestand eindigt nog steeds op.sh. Waarom kan het mislukken?---reveal---
De shebang kiest
sh, watdashkan zijn en mogelijk[[ ... ]]van Bash niet begrijpt. De extensie kiest de taal niet. Herstel een Bash-shebang voor Bash-functies, met#!helemaal aan het begin van de eerste regel. - 4UitlegLees het bestand eerst met Bash
Voer
bash folder-report.shuit. Dit start Bash en geeft het leesbare scriptbestand door; uitvoerrecht op het script is niet vereist. De gekozen interpreter is al Bash, dus de shebang maakt die keuze niet.Je zou een pad, een bestandslijst en de melding “Report finished” moeten zien. Relatieve paden die commando's in het script gebruiken, worden bepaald vanuit de werkdirectory, niet automatisch vanuit de map van het scriptbestand.
- 5VoorbeeldMaak directe uitvoering mogelijk
Voeg uitvoerrecht toe voor de eigenaar en voer het exacte pad uit:
chmod u+x folder-report.sh ./folder-report.shDe
./duidt de huidige directory aan. Directe uitvoering gebruikt de shebang van het bestand. Als het bestand leesbaar maar niet uitvoerbaar is, kan het eerderebash-commando werken terwijl dit commando mislukt met “Permission denied”. Rechten en de keuze van de interpreter zijn afzonderlijke onderdelen van het starten. - 6TipZoek het script op naam
Als je
folder-report.shzonder schuine streep typt, vraag je Bash om PATH te doorzoeken. De huidige directory staat normaal gesproken niet in die lijst.Met een persoonlijke bin-directory kun je het script vanuit andere mappen uitvoeren als die directory op PATH staat. Bekijk
echo "$PATH"en gebruikcommand -v folder-report.shom te zien welk uitvoerbaar bestand die naam kiest. Als een oude kopie eerder op PATH staat, verandert het bewerken van een nieuwere kopie elders niet wat deze naam uitvoert. - 7UitdagingHoud een directorywijziging in de juiste shell
Het script voert nu eerst
cd /var/loguit. Staat je terminal daar nadat./folder-report.shis geëindigd? Hoe kan een instellingenbestand de terminal daarheen verplaatsen?---reveal---
Het uitgevoerde script draait in een kindshell, dus de directorywijziging verplaatst de bovenliggende terminal niet. Als je een bestand inleest met
source ./settings.sh, worden de commando's in de huidige shell uitgevoerd en kan de directory van die sessie veranderen. Inlezen gebruikt de taal van de huidige shell. - 8UitdagingOnderzoek het starten voordat je commando's bewerkt
Een leesbaar overzicht werkt met
bash folder-report.sh. Directe uitvoering meldt “Permission denied” en alleen de naam typen meldt “command not found”. Welke twee problemen bij het starten moet je controleren?---reveal---
Controleer het uitvoerrecht van het script voor directe uitvoering. Controleer daarna PATH of gebruik het expliciete
./-pad om het te vinden. Een geldige Bash-shebang kiest de interpreter, maar kan geen rechten verlenen of het bestand op PATH plaatsen. - 9SamenvattingBij het starten maak je meerdere afzonderlijke keuzes
Het bestand bevat de reeks commando's. De interpreter leest de taal ervan, rechten maken directe uitvoering mogelijk en PATH of een schuine streep bepaalt waar het bestand staat.
Een uitgevoerd script werkt in een kindshell. Een ingelezen instellingenbestand werkt in de shell die al openstaat, zodat de toekenningen en directorywijzigingen in die sessie kunnen blijven bestaan.
2Maak een rapportnaam met datum zonder spaties te verliezen
11 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductieVolg een waarde naar een commando
- 2VoorbeeldSla een bestemming met meerdere woorden op
- 3VerbandGeef de instelling door aan een kindproces
- 4UitdagingScheid een naam van het achtervoegsel
- 5VoorbeeldBehoud het opgeslagen pad
- 6UitdagingKies vaste of veranderende tekst
- 7VoorbeeldVang een datum op voor de naam
- 8VoorbeeldBereken de waarde voordat je die invoegt
- 9UitdagingZoek het verloren breukdeel
- 10UitdagingCombineer het pad en de opgevangen waarde
- 11SamenvattingMaak onderscheid tussen de drie taken
3Voorkom dat een mislukte zoekopdracht een geslaagd rapport wordt
10 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductieBehandel het resultaat als onderdeel van de taak
- 2VoorbeeldZie de verborgen mislukking eerder in de pijplijn
- 3KernpuntLaat de pijplijn de mislukking melden
- 4UitdagingSla de relevante status op
- 5VoorbeeldHandel het mislukte werk expliciet af
- 6UitlegKies tussen syntaxiscontrole en uitvoering traceren
- 7UitlegLees de foutopties als afzonderlijke instellingen
- 8UitdagingLeg uit waarom dit script doorgaat
- 9UitdagingHoud de aanroeper op de hoogte
- 10SamenvattingLees zowel de gegevens als het resultaat
4Bekijk binnenkomende bestanden en lees hun records
15 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductieLaat elk soort invoer de volgende stap bepalen
- 2VoorbeeldKies een test voor het type pad
- 3UitlegVergelijk waarden op de juiste manier
- 4UitdagingInterpreteer een ontkende bestandstest
- 5VoorbeeldKies een actie met een commandoresultaat
- 6UitdagingVolg overlappende grenswaarden
- 7UitlegVergelijk een actiewoord met case
- 8VoorbeeldGeef een lus met een bestandsnaampatroon één bestand per doorgang
- 9UitdagingLeg uit wat er bij een lege map gebeurt
- 10TipKies een variabele getallengrens
- 11VoorbeeldLees een record zonder de spaties te splitsen
- 12UitdagingBehoud het laatste record zonder nieuweregelteken
- 13VerbandWacht zonder voortdurend te controleren
- 14UitdagingOnderzoek een totaal dat nul blijft
- 15SamenvattingStem de structuur af op de gegevens
5Accepteer bestandsinvoer en meld gedeeltelijke mislukking
10 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductieMaak invoer onderdeel van de commandoaanroep
- 2VoorbeeldBekijk de grenzen van de aanroep
- 3UitlegVerwerk de optie vooraan
- 4UitdagingTel een leeg argument mee
- 5VoorbeeldWijs een aanroep zonder bestandsinvoer af
- 6UitlegKies alleen voor optionele invoer een standaardwaarde
- 7VoorbeeldControleer de leesbewerking zelf
- 8UitdagingOnthoud de eerdere mislukking
- 9UitdagingStop de optieverwerking vóór een bestandsnaam met een koppelteken
- 10SamenvattingGeef herbruikbare commando's betrouwbare afspraken
6Plan een rapport en controleer de laatste uitvoering
12 stappen
Sla deze les op om elke Walkthrough stap voor stap te volgen.
- 1IntroductiePlan alleen werk waarvoor alle invoer beschikbaar is
- 2VoorbeeldLees een persoonlijke crontab-vermelding
- 3UitdagingVolg een stapgrootte in minuten over een uurgrens
- 4TipGeef de taak een uitvoerbestemming
- 5VerbandMaak onderscheid tussen een gemiste en een mislukte uitvoering
- 6VoorbeeldZet het werk in een service
- 7VoorbeeldZet de tijd in de bijbehorende timer
- 8UitlegLaad wijzigingen en schakel de planning in
- 9UitdagingControleer zowel het resultaat als de volgende tijd
- 10UitlegTel zo nodig tijd vanaf een gebeurtenis
- 11UitdagingKies voor inhalen na uitval
- 12SamenvattingBekijk de planning en de taak afzonderlijk
Shellscripts: oefenvragen
Set 1: Lees en voer kleine Bash-scripts uit10 Oefenvragen
Vraag 1 van 10
[[ ... ]], maar de eerste regel is #!/bin/sh. Op deze machine is sh gelijk aan dash. Welke eerste regel kiest de bedoelde interpreter?Toon antwoordVerberg antwoord
#!/bin/bash geeft Linux opdracht Bash te gebruiken als het bestand wordt uitgevoerd. De huidige shebang kiest dash, dat [[ ... ]] niet ondersteunt. Het woord “bash” toevoegen na /bin/sh zou nog steeds sh starten.Vraag 2 van 10
Toon antwoordVerberg antwoord
bash audit.sh start de interpreter en vraagt die het bestand te lezen, zodat uitvoerrecht op het script niet nodig is. ./audit.sh probeert het bestand direct uit te voeren en heeft dat recht dus nodig. Een bestand inlezen zou de commando's in de huidige shell uitvoeren, maar source bash audit.sh noemt het verkeerde bestand.Vraag 3 van 10
printf '<%s>\n' "$label" op als label="west side"?Toon antwoordVerberg antwoord
printf de waarde ontvangt. Een niet-afgeschermde expansie zou twee woorden opleveren; enkele aanhalingstekens rond die expansie zouden de letterlijke tekst $label opleveren.Vraag 4 van 10
file="shift notes.txt" in. Hoe moet het dat ene bestand naar de bestaande directory saved kopiëren?Toon antwoordVerberg antwoord
$file wordt gesplitst in “shift” en “notes.txt”, zodat cp twee bronnamen ontvangt. Enkele aanhalingstekens behouden de tekens $file letterlijk en vervangen die niet door het opgeslagen pad.Vraag 5 van 10
Toon antwoordVerberg antwoord
$? bevat de afsluitstatus van het meest recente commando, dus de onmiddellijke toekenning slaat 7 op. $# telt daarentegen positionele argumenten en kan het mislukte commando niet beschrijven. Voer geen ander commando uit voordat je het resultaat opslaat, want een nieuw commando zou de status vervangen die je wilt bewaren.Vraag 6 van 10
archive bestaat en is een directory. Wat zijn de resultaten van [ -f archive ] en [ -d archive ], in die volgorde?Toon antwoordVerberg antwoord
-f vereist een bestaand gewoon bestand, terwijl -d een bestaande directory vereist. De directory slaagt daarom niet voor de eerste test en wel voor de tweede. Alleen bestaan maakt niet beide tests waar: -e zou algemeen bestaan testen zonder een van deze specifieke typen te vereisen.Vraag 7 van 10
Wat toont deze code?
used=14
limit=20
percent=$(( used * 100 / limit ))
if [ "$percent" -ge 60 ]; then
used=$(( used + 2 ))
elif [ "$percent" -ge 70 ]; then
used=$(( used + 5 ))
fi
echo "$used"
Toon antwoordVerberg antwoord
used, wat 16 oplevert. Bash slaat daarna de elif-vertakking over, ook al zou die grenswaarde eveneens overeenkomen. Wie 5 optelt of beide wijzigingen toepast, ziet over het hoofd dat een if-reeks alleen de eerste geslaagde vertakking kiest.Vraag 8 van 10
./label.sh "East Wing" report.txt. Wat zijn $# en $2?Toon antwoordVerberg antwoord
report.txt is het tweede. $# is daarom 2 en $2 is report.txt. De scriptnaam hoort bij $0 en telt niet mee; als je de twee woorden binnen de afgeschermde naam afzonderlijk telt, kom je ten onrechte op drie argumenten.Vraag 9 van 10
dir=${1:-/srv/logs}. Het wordt aangeroepen met één argument: een lege tekenreeks tussen aanhalingstekens. Welke waarde wordt toegekend?Toon antwoordVerberg antwoord
:- kiest de standaardwaarde als de parameter niet is ingesteld of leeg is, dus een expliciet leeg eerste argument gebruikt /srv/logs. Het argument bestaat nog steeds in de positionele lijst, maar de lege waarde voldoet aan de voorwaarde voor de standaardwaarde. De vorm :? zou bij die invoer in plaats daarvan een fout melden.Vraag 10 van 10
25 4 * * * /home/rae/bin/audit.sh aan in een persoonlijke crontab?Toon antwoordVerberg antwoord
Set 2: Volg waarden, records en planningen10 Oefenvragen
Sla deze les op om elk antwoord te zien en elke set te oefenen.
Vraag 1 van 10
/bin/bash^M: bad interpreter, maar /bin/bash bestaat. Welke wijziging in het bestand verhelpt het aangeduide probleem?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 2 van 10
site?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 3 van 10
left=$(( 29 % 6 )) toe?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 4 van 10
done. Welk commando kan dat syntaxisprobleem detecteren zonder het script uit te voeren?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 5 van 10
[ 06 = 6 ] en [ 06 -eq 6 ], in die volgorde?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 6 van 10
a.csv en late batch.csv, beide gewone bestanden. Welke waarden worden gebruikt in for f in *.csv; do echo "$f"; done?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 7 van 10
Een bestand bevat oak, een nieuweregelteken en daarna elm zonder afsluitend nieuweregelteken. Welke telling wordt getoond?
count=0
while IFS= read -r line; do
count=$(( count + 1 ))
done < trees.txt
echo "$count"
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 8 van 10
./task.sh -v "blue room" output.txt voert het script shift uit. Wat zijn $1 en $# nu?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 9 van 10
*/25 10-12 * * * uitgevoerd en wanneer is de laatste uitvoering?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 10 van 10
inventory.timer?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Set 3: Volg gegevens door een volledig script10 Oefenvragen
Sla deze les op om elk antwoord te zien en elke set te oefenen.
Vraag 1 van 10
zone=west. Het bestand settings.sh bevat alleen zone=east. De terminal voert bash settings.sh uit, daarna source ./settings.sh en daarna bash -c 'echo "${zone:-unset}"'. De variabele is nooit geëxporteerd. Wat toont het laatste commando?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 2 van 10
echo "${name}_ready" met name=archive?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 3 van 10
completed=18 en total=32 op. Welk resultaat als geheel getal levert $(( completed * 100 / total )) op?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 4 van 10
Het bestand absent.log bestaat niet. Welke afsluitstatus bereikt de aanroeper?
#!/bin/bash
set -o pipefail
grep NOTICE absent.log | wc -l
status=$?
echo "Count ended"
exit "$status"
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 5 van 10
Wat toont dit script?
set -e
false || echo "Handled"
echo "Next"
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 6 van 10
*) in een case-blok na de patronen voor benoemde acties staan?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 7 van 10
De huidige directory bevat alleen de gewone bestanden draft one.jpeg, final.jpeg en notes.txt. Wat is de uitvoer?
count=0
for f in *.jpeg; do
[ "$f" = final.jpeg ] && continue
echo "${f%.jpeg}.jpg"
count=$(( count + 1 ))
done
echo "$count"
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 8 van 10
until [ -f /tmp/upload.ready ]; do sleep 3; done uit. Het gewone bestand bestaat al voordat de lus begint. Hoe vaak wordt het luslichaam uitgevoerd?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 9 van 10
status=0. Ongeldige invoer stelt status=1 in en latere invoer slaagt. Welke afsluiting meldt dat het verzoek onvolledig was?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 10 van 10
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Set 4: Onderzoek invoer, besturingsstroom en uitval10 Oefenvragen
Sla deze les op om elk antwoord te zien en elke set te oefenen.
Vraag 1 van 10
weekly.sh naar weekly, met ongewijzigde inhoud en rechten. Wat doet het verdwijnen van de extensie met de keuze van de interpreter op basis van de shebang door Linux?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 2 van 10
export REGION=north uit en start daarna een script dat REGION=south toekent en eindigt. Welke waarde blijft in het ouderproces staan?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 3 van 10
pattern="*.txt" in. Welk argument ontvangt touch "$pattern"?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 4 van 10
Wat gebeurt er in dit niet-interactieve script?
set -eu
dest=
if [ -z "$dest" ]; then
dest=${2:-/srv/archive}
fi
echo "$dest"
Het script ontvangt slechts één argument, input.txt.
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 5 van 10
De variabele count bevat 10 en de huidige directory is schrijfbaar en bevat geen bestand met de naam 4. Wat gebeurt er?
if [ "$count" > 4 ]; then
echo "High"
else
echo "Low"
fi
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 6 van 10
case "$value" in [0-9]*) echo "Match" ;; *) echo "No" ;; esac. Wat gebeurt er bij value=8draft?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 7 van 10
Wat wordt getoond?
i=0
total=0
while [ "$i" -lt 4 ]; do
i=$(( i + 1 ))
[ "$i" -eq 2 ] && continue
total=$(( total + i ))
[ "$total" -gt 5 ] && break
done
echo "$i:$total"
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 8 van 10
-v, een lege tekenreeks tussen aanhalingstekens en "red room". Het voert shift uit en daarna for arg in "$@"; do echo "<$arg>"; done. Wat wordt getoond?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 9 van 10
0 11 9 * 2 /home/rae/bin/check.sh in gewone cron?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 10 van 10
Persistent=true. Drie dagelijkse activeringen verstrijken terwijl de computer uitstaat. Welke inhaalactie regelt de timer bij heractivering?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Set 5: Combineer afscherming, foutcontroles en herbruikbare invoer10 Oefenvragen
Sla deze les op om elk antwoord te zien en elke set te oefenen.
Vraag 1 van 10
Een Bash-terminal staat in /home/rae, met PATH /home/rae/bin:/usr/local/bin:/usr/bin:/bin. In beide bin-mappen en de huidige directory staan uitvoerbare Bash-scripts met de naam scan. Elk bevat alleen een Bash-shebang en cd /srv/cache; die directory bestaat en is toegankelijk. Welk bestand voert het eerste commando uit en welke paden worden getoond?
scan
pwd
source ./scan
pwd
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 2 van 10
a.txt en b.txt. Hoeveel gegevensargumenten maakt printf '<%s>\n' $value op na value="*.txt spare", met de standaardinstellingen van Bash voor splitsing en bestandsnaamexpansie?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 3 van 10
ready op standaarduitvoer en warning op standaardfoutuitvoer en slaagt daarna. Wat wordt opgeslagen door message=$(the_command)?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 4 van 10
Welke afsluitstatus bereikt de aanroeper?
#!/bin/bash
false
saved=$?
true && echo "Handled"
exit $(( saved + 2 ))
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 5 van 10
set -u en heeft al folder="" toegekend. Het moet met een bruikbare foutmelding stoppen voordat het een ontbrekende of lege map gebruikt. Welke expansie biedt die controle?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 6 van 10
"$text" een lengte anders dan nul heeft?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 7 van 10
for i in {1..$limit}; do echo "$i"; done bij limit=3 onder gewone Bash-expansie?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 8 van 10
Welke telling wordt getoond bij het standaardgedrag van Bash voor pijplijnen? Het bestand bevat drie regels die elk eindigen met een nieuweregelteken.
count=5
cat tasks.txt | while IFS= read -r line; do
count=$(( count + 1 ))
done
count=$(( count + 2 ))
echo "$count"
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 9 van 10
Een script verwerkt zijn invoer met deze code en vereist daarna precies twee bestandsargumenten. Hoeveel argumenten blijven over na de aanroep ./copy.sh -v -- "early notes.txt" -final.txt en wat moet daarna gebeuren?
while [ "$#" -gt 0 ]; do
case "$1" in
-v) verbose=1; shift ;;
--) shift; break ;;
-*) echo "Unknown option" >&2; exit 2 ;;
*) break ;;
esac
done
Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Vraag 10 van 10
/home/rae/.local/bin. Welke wijziging verhelpt het waarschijnlijke verschil?Toon antwoordVerberg antwoord
Sla deze les op om dit antwoord te zien.
Kom je niet uit je eigen opgave? Huiswerkhulp
Kernbegrippen
A
Aantal argumenten
$#, zonder de aanroepnaam mee te tellen../greet.sh Ana "Lee Kim" omdat de afgeschermde naam één argument is.Accolade-expansie
{1..5} voordat Bash variabele-expansie op het commando toepast.{1..$n} niet omzetten in een bereik op basis van de waarde die in n is opgeslagen.Afscherming
"$file" af te schermen blijft “monthly report.txt” één argument bij het kopiëren van het bestand.Afsluitstatus
grep -q maakt onderscheid tussen een overeenkomst, geen overeenkomst en een probleem bij het lezen van de invoer.Afsluitstatus van een pijplijn
pipefail die regel verandert.grep mislukt maar de daaropvolgende wc succesvol geen invoer telt.Allesomvattend patroon
* aan het einde van een Bash-case-blok.*) meldt onbekende commando's nadat de benoemde subcommando's zijn gecontroleerd.Anacron
B
Bash
[[ ... ]] gebruikt, kiest Bash in de shebang zodat de syntaxis van de testconstructie wordt begrepen.Bestandseinde
read meldt mislukking als het dit punt bereikt.read mislukking meldt.Bestandsnaamexpansie
*.log naar afzonderlijke overeenkomende bestandsnamen voordat een for-lus begint.Bestandstest
[ -d "$src" ] accepteert een brondirectory maar wijst een gewoon bestand af.break
C
case
Commandosubstitutie
$(command), waarbij nieuweregeltekens aan het einde worden verwijderd.today=$(date +%F) vangt een datum op voor gebruik in de naam van een back-upbestand.Commentaar
# aan het begin van een woord buiten afgeschermde tekst.# Keep a copy for recovery legt uit waarom de volgende bestandskopie nodig is.continue
cron
Crontab
crontab -l toont de crontab van de huidige gebruiker, zodat je de planningen kunt bekijken.D
Doorgeven van argumenten
"$@" om elke grens te behouden."$@" door te geven blijven een lege invoer en een naam met meerdere woorden afzonderlijke argumenten.Dubbele aanhalingstekens
echo "Home: $HOME *" laten het pad naar de homedirectory expanderen en behouden het sterretje.E
elif
Enkele aanhalingstekens
echo '$HOME' de tekens “$HOME” toont in plaats van een pad naar de homedirectory.errexit
set -e, die stopt bij niet-afgehandelde mislukkingen en daarbij bepaalde situaties toestaat waarin een commandostatus wordt getest.if-voorwaarde de else-vertakking kiezen in plaats van het script te beëindigen.exit
exit 2 na verkeerd gebruik, zodat de aanroeper een resultaat krijgt dat mislukking aangeeft.Exporteren
F
for-lus
web1 web2 db1 voert het luslichaam één keer uit voor elk van de drie hostnamen.Foutvlag
G
Gebruikersbeheer zonder aanmeldsessie
Gebruiksinstructie
Geheeltallige deling
$(( 7 / 2 )) de waarde 3 op, hoewel het exacte quotiënt 3,5 is.I
IFS
read leeg instelt, blijft witruimte aan het begin en einde behouden.IFS= read -r line behoud je spaties aan de randen van elk record dat uit het invoerbestand wordt gelezen.Inlezen in de huidige shell
./settings.sh in te lezen laad je de variabeletoekenningen direct in de open Bash-sessie.Interpreter
#!/usr/bin/python3 wordt gekozen, leest Python-code in plaats van Bash-commando's.Iteratie
K
Kalendertimer
OnCalendar=Mon..Fri 09:00 kiest werkdagen om 09.00 uur.Kindproces
Kortsluitevaluatie
&& of || wordt uitgevoerd.cd /data || exit 1 stopt afhankelijke commando's na een mislukte directorywijziging.L
Logboek
journalctl -u backup.service toont meldingen van de back-uptaak.M
Minimale omgeving
Monotone timer
N
Negatie
[ ! -d "$p" ] accepteert zowel een gewoon bestand als een pad dat niet bestaat.nounset
set -u, die expansie van een niet-ingestelde variabele in een niet-interactief script als fout behandelt.Numerieke vergelijking
-eq en -gt, onafhankelijk van hun tekstlengte.[ "$count" -ge 8 ] slaagt bij een opgeslagen telling van 12.O
Omgevingsvariabele
Optie
-v kan extra meldingen inschakelen voordat het script de resterende bestandsnamen verwerkt.P
PATH
job.sh, maar volgt het expliciete pad in de huidige directory bij ./job.sh.pipefail
grep wordt gemeld de hele pijplijn laten mislukken.Positionele parameter
$1, waarbij voor posities na negen accolades vereist zijn.${10} haalt het tiende argument op zonder een nul achter $1 toe te voegen.R
read
read -r -p "Name: " name vraag je om een naam en behoud je backslashes in de ingevoerde tekst.Regeleinde
^M.Rekenkundige expansie
$(( ... )) en voegt de berekende waarde in het commando in."$(( count + 1 ))" in de volgende tellerwaarde als geheel getal.Rest
%.$(( 17 % 5 )) is 2 omdat drie volledige groepen van vijf samen 15 gebruiken.S
Service-unit
backup.service bepaalt het script dat door de bijbehorende back-uptimer wordt geactiveerd.Shebang
#! en de interpreter aanwijst die Linux moet gebruiken om een script uit te voeren.#!/bin/bash begint bij het eerste teken, vóór commentaar of een lege regel.Shellscript
shift
-v heeft verwerkt en verwijderd, wordt het volgende commandoregelwoord $1 voor de optieverwerker.Signaal- en gebeurtenisafhandeling
Sleutelwoord voor een testconstructie
[[ in Bash, begint een shelltestconstructie met eigen regels voor verwerking en patroonherkenning.[[ staat [[ $name == *.log ]] toe zonder woordsplitsing van de naam.Standaardfoutuitvoer
>&2 naar standaardfoutuitvoer wordt gestuurd, blijft zichtbaar als standaarduitvoer naar een bestand gaat.Standaardwaarde
${1:-/var/log} voor een ontbrekend of leeg argument.Stapgrootte in een cron-tijdveld
*/45 in het minutenveld kiest 0 en 45 en begint daarna bij 0 in het volgende uur.Syntaxiscontrole
bash -n detecteert een ontbrekende done voordat de lus commando's kan uitvoeren.T
Tekenreeksvergelijking
Teller
count=0 is geïnitialiseerd, kan één keer toenemen voor elke regel die een lus leest.Timerunit
backup.timer in te schakelen stel je de planning voor de back-upservice vast.Toekenning
name=value, zonder spaties rond het isgelijkteken.name="Lee Kim" houdt de twee woorden bij elkaar als één opgeslagen waarde.U
Uitvoering traceren
bash -x wordt een leeg bronargument zichtbaar dat aan een kopieercommando wordt doorgegeven.Uitvoerrecht
chmod u+x job.sh kan de eigenaar proberen ./job.sh uit te voeren.until-lus
V
Validatie
Variabele
city slaat “Lisbon” op na city=Lisbon, zodat echo "$city" die kan tonen.Variabele-expansie
"${file}_old" in “report_old” als file de waarde “report” bevat.Vertakking
Verwijderen van een achtervoegsel
${f%.jpeg}.W
while-lus
read het bestandseinde bereikt en mislukking meldt.Woordsplitsing
cp draait.Over deze les
Door StudeliFout melden
Maak je eigen Studiemateriaal
Maak van je aantekeningen, slides en documenten Leermodules, Oefenvragen, Flashcards en 6 andere tools.