Bash skripte 2 — promenljive i argumenti
U prvom delu napravili smo skriptu koja svaki put radi isto. Da bi radila sa različitim ulazima — različitim fajlom, direktorijumom ili imenom servisa — trebaju ti promenljive.
Dodela vrednosti
ime="Alen" broj=42 putanja="/var/log/httpd"
Znak $ ispred imena vraća vrednost:
#!/usr/bin/env bash ime="Alen" echo "Zdravo, $ime"
Zdravo, Alen
Bez razmaka oko znaka jednakosti
Ovo je greška koju svi naprave bar jednom:
ime = "Alen"
-bash: ime: command not found
Sa razmakom bash misli da je ime komanda, a
= i "Alen" njeni argumenti. Piši
ime="Alen", bez razmaka ni sa jedne strane.
Imena promenljivih
Slova, brojevi i donja crta; ne smeju počinjati brojem. Bash razlikuje
mala i velika slova — ime i IME su dve različite
promenljive.
Uobičajena praksa: mala slova za svoje promenljive, velika za konstante na vrhu skripte i za promenljive okruženja.
LOG_DIR="/var/log/httpd" MAX_DANA=30 danasnji_log="$LOG_DIR/error_log"
Vitičaste zagrade
Kad se odmah do imena promenljive nalazi tekst, bash ne zna gde ime prestaje:
fajl="backup" echo "$fajl_2026.tar.gz"
.tar.gz
Bash je tražio promenljivu fajl_2026, koja ne postoji.
Zagrade rešavaju granicu:
echo "${fajl}_2026.tar.gz"
backup_2026.tar.gz
Neki uvek pišu ${ime} radi doslednosti. Nije obavezno, ali
ne škodi.
Navodnici
Ovo je mesto gde bash najviše iznenađuje početnike, pa vredi pažljivo.
Dvostruki navodnici — promenljive se zamenjuju
ime="Alen" echo "Zdravo, $ime"
Zdravo, Alen
Jednostruki navodnici — sve doslovno
echo 'Zdravo, $ime'
Zdravo, $ime
Bez navodnika — opasno
Bash rastavlja vrednost po razmacima i tumači specijalne znake:
fajl="moj dokument.txt" rm $fajl # pokušava da obriše "moj" i "dokument.txt" rm "$fajl" # briše "moj dokument.txt"
Pravilo koje ti štedi sate traženja greške: promenljive uvek piši u dvostrukim navodnicima, osim kad tačno znaš zašto ne bi.
Ovo nije stilska preporuka. Skripta koja radi na tvom test fajlu
backup.txt lako pukne na produkcijskom
backup stari.txt — a sa rm to nije bezopasan
kvar.
Rezultat komande u promenljivoj
Zapis $( ) izvršava komandu i vraća njen izlaz:
datum=$(date +%Y-%m-%d) korisnik=$(whoami) broj_fajlova=$(ls -1 | wc -l) echo "Danas je $datum, prijavljen si kao $korisnik" echo "U ovom direktorijumu ima $broj_fajlova stavki"
Ovo je osnovni alat za pravljenje imena fajlova sa datumom:
ime_backupa="baza_$(date +%Y%m%d_%H%M).sql" echo "$ime_backupa"
baza_20260821_1435.sql
Videćeš i stariji zapis sa obrnutim apostrofima — `date`.
Radi isto, ali se ne može ugnežđivati i teško se razlikuje od običnog
apostrofa. Koristi $( ).
Argumenti komandne linije
Ovo je ono što skriptu čini upotrebljivom. Vrednosti koje joj proslediš pri pokretanju dostupne su preko numerisanih promenljivih:
#!/usr/bin/env bash echo "Ime skripte: $0" echo "Prvi argument: $1" echo "Drugi argument: $2" echo "Ukupno argumenata: $#" echo "Svi argumenti: $@"
$ ./test.sh alfa beta Ime skripte: ./test.sh Prvi argument: alfa Drugi argument: beta Ukupno argumenata: 2 Svi argumenti: alfa beta
| Zapis | Značenje |
|---|---|
$0 | ime skripte |
$1 … $9 | prvi do deveti argument |
${10} | deseti i dalje — obavezne zagrade |
$# | broj argumenata |
$@ | svi argumenti, svaki kao zasebna stavka |
$? | izlazni kod prethodne komande |
$$ | PID same skripte |
Praktičan primer
#!/usr/bin/env bash # Pregled poslednjih grešaka servisa # Upotreba: ./greske.sh ime-servisa servis="$1" echo "Poslednjih 20 zapisa za servis: $servis" journalctl -u "$servis" -n 20 --no-pager
$ ./greske.sh httpd $ ./greske.sh sshd
Jedna skripta, bilo koji servis. Više o journalctl-u u posebnoj lekciji.
Provera da je argument prosleđen
Ako korisnik ne prosledi ništa, $1 je prazno i skripta radi
nešto neočekivano. Zaustavi je odmah:
#!/usr/bin/env bash
if [ -z "$1" ]; then
echo "Upotreba: $0 ime-servisa"
exit 1
fi
servis="$1"
journalctl -u "$servis" -n 20 --no-pager
Oznaka -z proverava da li je vrednost prazna. Detaljno o
uslovima u sledećem delu — ovaj obrazac zapamti kao gotov, jer ide na
početak skoro svake skripte koja prima argumente.
$@ i $* nisu isto
"$@" svaki argument ostaje zasebna stavka "$*" svi argumenti spojeni u jedan string
Skoro uvek ti treba "$@", sa navodnicima. Jedino tako
argumenti koji sadrže razmake ostaju celi.
Podrazumevane vrednosti
Ako argument nije prosleđen, uzmi zadatu vrednost:
broj_redova="${1:-20}"
direktorijum="${2:-/var/log}"
echo "Prikazujem $broj_redova redova iz $direktorijum"
$ ./skripta.sh Prikazujem 20 redova iz /var/log $ ./skripta.sh 50 /var/log/httpd Prikazujem 50 redova iz /var/log/httpd
Srodni oblik prekida rad sa porukom ako promenljiva nije postavljena:
servis="${1:?Moraš navesti ime servisa}"
Unos od korisnika
Komanda read čeka da korisnik nešto otkuca:
#!/usr/bin/env bash read -p "Kako se zoveš? " ime echo "Zdravo, $ime"
Bez ispisivanja na ekran, za lozinke:
read -sp "Lozinka: " lozinka echo
Sa vremenskim ograničenjem:
read -t 10 -p "Nastavi? (d/n) " odgovor
Napomena: read je koristan dok skriptu koristiš
ručno, ali skripta koju pokreće
cron nema kome da
postavi pitanje — tu se zaglavi i visi. Za automatizovane poslove sve
prosleđuj kao argumente.
Aritmetika
Bash podrazumevano radi sa tekstom. Za računanje koristi
$(( )):
a=10 b=3 echo $((a + b)) # 13 echo $((a - b)) # 7 echo $((a * b)) # 30 echo $((a / b)) # 3 -- celobrojno deljenje! echo $((a % b)) # 1 -- ostatak
Unutar zagrada $ ispred imena nije obavezan.
Uvećavanje brojača:
brojac=0 brojac=$((brojac + 1))
Bash ne zna za decimalne brojeve. Ako ti trebaju, koristi
bc:
echo "scale=2; 10 / 3" | bc
3.33
Promenljive okruženja
Neke promenljive postoje pre nego što ih ti postaviš:
echo "$HOME" # /home/alen echo "$USER" # alen echo "$PWD" # trenutni direktorijum echo "$PATH" echo "$HOSTNAME"
Ceo spisak daje env. Ove promenljive slobodno koristi u
skriptama, ali izbegavaj da im dodeljuješ svoje vrednosti — naročito
PATH i HOME.
export
Promenljiva je podrazumevano vidljiva samo u skripti u kojoj je napravljena. Da bi je videli i programi koje ta skripta pokreće:
export APP_MODE="production" ./druga-skripta.sh
Obrada teksta u promenljivoj
Bash ume dosta i bez pozivanja spoljnih alata:
fajl="/var/log/httpd/error_log.gz"
echo "${#fajl}" # dužina: 29
echo "${fajl##*/}" # samo ime fajla: error_log.gz
echo "${fajl%/*}" # samo putanja: /var/log/httpd
echo "${fajl%.gz}" # bez nastavka: /var/log/httpd/error_log
echo "${fajl/log/LOG}" # zamena prvog pojavljivanja
echo "${fajl//log/LOG}" # zamena svih pojavljivanja
Zapisi nisu lepi za pamćenje, ali su brzi i ne pokreću novi proces — što je bitno u petljama sa hiljadama ponavljanja. Za složenije stvari tu su sed i awk.
Primer: skripta za backup direktorijuma
#!/usr/bin/env bash
# Arhivira zadati direktorijum sa datumom u imenu
# Upotreba: ./backup.sh /putanja/do/direktorijuma [odrediste]
izvor="$1"
odrediste="${2:-/backup}"
if [ -z "$izvor" ]; then
echo "Upotreba: $0 /putanja/do/direktorijuma [odrediste]"
exit 1
fi
datum=$(date +%Y%m%d_%H%M)
naziv=$(basename "$izvor")
arhiva="$odrediste/${naziv}_${datum}.tar.gz"
echo "Arhiviram $izvor u $arhiva"
tar -czf "$arhiva" "$izvor"
echo "Gotovo. Veličina: $(du -h "$arhiva" | cut -f1)"
$ ./backup.sh /etc/httpd Arhiviram /etc/httpd u /backup/httpd_20260821_1435.tar.gz Gotovo. Veličina: 84K
Skripta još ne proverava da li izvor postoji, da li je tar uspeo, niti briše stare arhive. Sve to dodajemo u naredna dva dela.
Vežba
Napiši skriptu koja prima ime korisnika kao argument i ispisuje:
- njegov UID i grupe (id)
- njegov home direktorijum
- koliko taj home zauzima (du -sh)
- kada se poslednji put prijavio (
lastlog -u)
Ako argument nije prosleđen, neka koristi trenutno prijavljenog korisnika kao podrazumevanu vrednost.
Sledeći deo: uslovi i petlje — kako da skripta donosi odluke i ponavlja posao nad više fajlova.
Povezano: Bash skripte 1 — prva skripta · Piping i redirekcija · Programiranje
Comments
Post a Comment