Mi az a shell script?
- Tulajdonképpen közönséges szövegfileok.
- Első megközelítésben ugyanazokat a parancsokat tartalmazhatja, amelyekete parancssorból is kiadhatunk
- Mi kell a futtatáshoz?
- "Magic number" (#!/bin/bash)
- x jog (vagy: bash script_nev)
- Elérési úttal kell futtatni (vagy: export PATH=$PATH:. )
Néhány egyszerű példa
#!/bin/bash
# Ez egy megjegyzés
echo "Hello világ!"
echo "Hello $USER!"
echo 'Hello $USER!'
echo "Hello ${USER}!"
echo 'Hello ${USER}!'
echo "Hello $USERalma"
echo 'Hello $USERalma'
echo "Hello ${USER}alma"
echo 'Hello ${USER}alma'
exit 0
#!/bin/bash
clear
echo "Program starts now."
echo "Hello, $USER"
echo
echo "Today's date is `date`"
echo
echo "These users are currently connected:"
who | cut -d' ' -f1 | sort -u
echo
echo "This is `uname -s` running on a `uname -m` processor."
echo
echo "This is the uptime information:"
uptime
echo
echo "That's all folks!"
exit 0
Változók használata
Mi következik ebből?
- Ha mi a scriptünkben létrehozunk egy változót, az csak a scripten belül "látszik", hiszen a scriptünk egy külön
shellben fut a forkolás miatt, és azt már láttuk, hogy a shellek lokális változói nem látszanak a külvilág felé
SŐT: Változók használata
- Megoldás: exportálás, ahogy azt már láttuk
- MEGJEGYZÉS: A forkolást ki lehet kerülni, ha a következő formában futtatjuk a scriptünket:
source scriptnev
. scriptnev
#!/bin/bash
szam=43
szoveg1="Hello világ"
echo $szam
echo $szoveg1
szoveg2=szam
echo $szoveg2
szoveg2=$szam
echo $szoveg2
exit 0
- A script futtatása után próbáljuk ki az
echo $szam
parancsot, így láthatjuk, hogy a 'szam' változó valóban csak a scripten belül volt elérhető
- Tegyük meg ugyanezt úgy, hogy .-tal futtatjuk
Speciális bash (belső)változók
$$ | A process azonosítója (PID) |
$? | Az előzőleg futott program státuszkiemente |
$# | A parancssori paraméterek száma |
$0 | Az adott héjprogram neve |
$1,$2,...,$9,${10} | A scriptnek átadott parancssori paraméterek |
$* | Valamennyi paraméter egyben egy karakterláncként ("$1 $2 ...") |
$@ | Valamennyi paraméter egyben, de külön idézõjelbe téve ("$1" "$2" ...) |
"$@" | ""$1" "$2" ..." |
#!/bin/bash
echo '$# értéke:' $#
echo
echo '$* értéke:' $*
echo '$@ értéke:' $@
echo '"$@" értéke:' "$@"
echo
echo "Első paraméter: "$1""
echo "Második paraméter: "$2""
echo
X="$1""$2"
echo "Összefűzve: "$X""
exit 0
shift utasítás
- A parancssori paramétereket tudjuk léptetni vele
- Hatására a legelső ($1) parancssori paraméter elveszik a többi ($2,$3,..) pedig eggyel előbbre lép
- Természetesen a $# értéke is csökken 1-gyel
Az összes parancssori paraméter feldolgozása - variációk egy témára
Klasszikus
for i in $@
do
echo $i
done
Ötletes
while [ $# -gt 0 ]
do
echo $1
shift
done
Veszélyes - könnyű elrontani
for((i=1;i<=$#;i++))
do
echo ${!i}
done
Még néhány szó a változókról
#!/bin/bash
echo $szam
echo ${szam-0}
echo $szam
echo ${szam=0} #használható ehelyett: echo ${szam:=0}
echo $szam
unset szam
echo ${szam?"hiba"}
exit 0
#!/bin/bash
szam=3
$szam | masik_program #HIBÁS
echo $szam | masik_program
szoveg=""
cat f1.txt > szoveg #HIBÁS
szoveg=`cat f1.txt`
exit 0
Vezérlési szerkezetek
if elágazás
if TEST-COMMANDS
then
.....
else
....
fi
A test parancs segítségével tudunk logikai feltételeket megfogalmazni, azonban bash-ban a [ ] zárójelpárral egyszerűsíthető az írásmód
[ -e FILE ] True if FILE exists.
[ -d FILE ] True if FILE exists and is a directory.
[ -f FILE ] True if FILE exists and is a regular file.
[ -h FILE ] True if FILE exists and is a symbolic link.
[ -L FILE ] True if FILE exists and is a symbolic link.
[ -r FILE ] True if FILE exists and is readable.
[ -w FILE ] True if FILE True if FILE exists and is writable.
[ -x FILE ] True if FILE exists and is executable.
[ -s FILE ] True if FILE exists and has a size greater than zero.
[ -z STRING ] True of the length of "STRING" is zero.
[ -n STRING ] True of the length of "STRING" is non-zero.
[ STRING ] True of the length of "STRING" is non-zero.
[ STRING1 == STRING2 ] True if the strings are equal.
"=" may be used instead of "==" for strict POSIX compliance.
[ STRING1 != STRING2 ] True if the strings are not equal.
[ STRING1 < STRING2 ] True if "STRING1" sorts before "STRING2" lexicographically in the current locale.
[ STRING1 > STRING2 ] True if "STRING1" sorts after "STRING2" lexicographically in the current locale.
[ ARG1 OP ARG2 ] "OP" is one of:
-eq (=)
-ne (!=)
-lt (<)
-le (<=)
-gt (>)
-ge (>=)
"ARG1" and "ARG2" are integers.
[ ! EXPR ] True if EXPR is false.
[ ( EXPR ) ] Returns the value of EXPR.
This may be used to override the normal precedence of operators.
[ EXPR1 -a EXPR2 ] True if both EXPR1 and EXPR2 are true.
[ EXPR1 -o EXPR2 ] True if either EXPR1 or EXPR2 is true.
-------------------------------------------------------------
[ -b FILE ] True if FILE exists and is a block-special file.
[ -c FILE ] True if FILE exists and is a character-special file.
[ -g FILE ] True if FILE exists and its SGID bit is set.
[ -k FILE ] True if FILE exists and its sticky bit is set.
[ -p FILE ] True if FILE exists and is a named pipe (FIFO).
[ -S FILE ] True if FILE exists and is a socket.
[ -u FILE ] True if FILE exists and its SUID (set user ID) bit is set.
[ -t FD ] True if file descriptor FD is open and refers to a terminal.
[ -O FILE ] True if FILE exists and is owned by the effective user ID.
[ -G FILE ] True if FILE exists and is owned by the effective group ID.
[ -N FILE ] True if FILE exists and has been modified since it was last read.
[ FILE1 -nt FILE2 ] True if FILE1 has been changed more recently than FILE2,
or if FILE1 exists and FILE2 does not.
[ FILE1 -ot FILE2 ] True if FILE1 is older than FILE2, or is FILE2 exists and FILE1 does not.
[ FILE1 -ef FILE2 ] True if FILE1 and FILE2 refer to the same device and inode numbers.
[ -o OPTIONNAME ] True if shell option "OPTIONNAME" is enabled.
-----------------------------------------------------------------
#!/bin/bash
if [ $# -gt 0 ]
then
echo "Adtak meg paramétert"
if [ "$1" = "-h" -o "$1" = "--help" ]
then
echo "Segítek!!"
exit 0
fi
else
echo "Nem adtak meg paramétert!" >&2
exit 1
fi
echo "Ez mikor fog megjelenni?"
exit 0
#!/bin/bash
if [ "$(whoami)" != "root" ]; then
echo "You have no permission to run $0 as non-root user." >&2
exit 1;
fi
#ide jön a tényleges kód
exit 0
#!/bin/bash
# This script gives information about a file.
FILENAME="$1"
echo "Properties for $FILENAME:"
if [ -f $FILENAME ]
then
echo "Size is $(ls -lh $FILENAME | awk '{ print $5 }')"
echo "Type is $(file $FILENAME | cut -d":" -f2)"
echo "Inode number is $(ls -i $FILENAME | cut -d" " -f1)"
else
echo "File does not exist."
fi
exit 0
Speciális kétirányú elágazás
expr ? expr : expr
X=5
Y=$(($X==0 ? 1 : $X))
echo Y
case elágazás
case EXPRESSION in
CASE1) COMMAND-LIST;;
CASE2) COMMAND-LIST;;
...
CASEN) COMMAND-LIST;;
esac
Az egyes ágak feltételeiben a joker helyettesítési szabáloky érvényesek!
case-nél illetve test ([ ])-nél nem használhatók a szabályos kifejezések!
#!/bin/bash
if [ $# -eq 0 ]
then
echo "Adjon meg parametert!" >&2
exit 1
fi
case $1 in
0) echo "Nulla";;
1) echo "Egy";;
2) echo "Ketto";;
3) echo "Harom";;
4) echo "Negy";;
5) echo "Ot";;
*) echo "Otnel nagyobb szam";;
esac
exit 0
#!/bin/bash
KERDES="Szereted a Linuxot? [i/n] "
echo -n $KERDES
read VALASZ
case $VALASZ in
i*|I*) echo "Örülök"; exit 0;;
n*|N*) echo "Majd megszereted"; exit 0;;
*) echo "Válaszolj Igennel vagy Nemmel!"; exit 1;;
esac
for ciklus
for NAME [in LIST ]
do
COMMANDS
done
Alapvetően egy for ciklussal egy lista elemein tudunk végigmenni. Az egyes elemeket egymástól WP-ek választják el egymástól.
#!/bin/bash
for i in a b c d e
do
echo $i
done
echo
for i in a b "c d" e
do
echo $i
done
exit 0
#!/bin/bash
for i in `cat lista.txt`
do
echo -n "File: "$i""
cp "$i" "$i".bak
echo " copied"
done
exit 0
while ciklus
while TEST-COMMANDS
do
COMMANDS
done
- Úgy működik, mint pl a C-ben megismert while ciklus
- A feltétel megadása úgy történik, mint az if-nél ( test <=> [ ] )
until ciklus
until TEST-COMMANDS
do
COMMANDS
done
- nem a szokásos hátultesztelős ciklus
- nem biztos hogy egyszer lefut a ciklusmag
- kilépési feltételt kell megadni, azaz a ciklus addig fut, amíg a feltétel igaz nem lesz
- Igazából ugyanaz, mint a while ciklus az egyetlen különbség, hogy a while-nál bentmaradási feltételt kell megadni, itt pedig kilépésit
#!/bin/bash
echo "for ciklus:"
for i in `seq 10`
do
echo $i
done
echo
echo "while ciklus:"
i=1
while [ $i -le 10 ]
do
echo $i
i=`expr $i + 1`
done > szamok.txt
echo
echo "until ciklus:"
i=1
until [ $i -gt 10 ]
do
echo $i
i=`expr $i + 1`
done | tee szamok2.txt
exit 0
Ami kimaradt eddig
Tömbök
- Csak 1 dimenzios tömböket használhatunk
- 0-tól indexelődik, mint C-ben
- Nincs méretkorlát és nem kell előre megadni, hogy mekkore vektort akarunk használni
- Ugyanúgy működik, mint a sima változók
- Létrehozás/Értékadás:
ARRAY=(value1 value2 ... valueN)
Ilyenkor a tömb első N elemének értéket adunk, azaz ARRAY[0]-nak, ARRAY[1]-nek,...., ARRAY[N-1]-nek
ARRAY[NUM]=value
Ilyenkor egyetlen elemnek adunk értéket
- Egy tömb összes elemének kiírása:
echo ${ARRAY[*]}
- Egy adott elem kiírása:
echo ${ARRAY[2]}
ARRAY=(one two three)
echo ${ARRAY[*]}
echo $ARRAY[*]
echo ${ARRAY[2]}
ARRAY[3]=four
echo ${ARRAY[*]}
unset ARRAY[1]
echo ${ARRAY[*]}
unset ARRAY
echo ${ARRAY[*]}
Néhány trükk
STR="ABCDEFGH"
echo ${#STR} # kiírja hány karakterből áll STR
echo ${STR:start:hossz} # részstringet lehet kivágni:
# 'start'. karaktertől 'hossz' db karaktert ad vissza
# 0-tól kezdődik a poziciók számolása
echo ${STR:start} # a 'start'. karaktertől kezdve a string végégig
echo ${#ARRAY} # tömb elemszáma
echo ${STR/PATTERN/NEWSTRING} # STR-ben a PATTERN-nek megfelelő
# mintát cseréli NEWSTRING-re
# Tegyük fel, hogy csináltunk 3 változót: cica1, cica2, cica3
cica1=10
cica2=20
cica3=30
# Hogyan tudjuk ügyesen kiratni (vagy bármire felhasznáni) a változók értékeit?
for((i=1;i<4;i++))
do
echo $((cica$i))
# Figyelem: az echo $cica$i nem működik! Gondoljátok meg, hogy miért...
# Megjegyzés: ugyanúgy jó megoldás az
# eval echo \$cica$i
# de ez sokkal rondább :)
done
Függvények
#!/bin/bash
Osszead1()
{
szam1=5
szam2=7
echo $((szam1+szam2))
}
Osszead1
szam1=3
Osszead1
exit 0
#!/bin/bash
Osszead2()
{
szam1=$1 # FIGYELEM!! NEM A PARANCSSORI PARAMÉTEREK!!
szam2=$2 # HANEM A FV. SAJÁT PARAMÉTEREI!!
echo $((szam1+szam2))
}
Osszead2 4 5
Osszead2 $1 $2 #parancssori paraméterek
exit 0