هذا الجزء لم يُترجم بعد. أنت ترى النص الإنجليزي.
$ مستخدم عادي# بصلاحية root (أو مع sudo)
أهداف الامتحان في هذا الفصل
- تنفيذ الكود فقط عندما يكون الاختبار صحيحًا (if و test و [ ])
- استخدام الحلقات (for وغيرها) لمعالجة الملفات والمدخلات
- استخدام مدخلات السكربت ($1 و $2 وغيرها)
- استخدام مخرجات الأوامر داخل السكربت
Write your first script
A script starts with the shebang line (#!/bin/bash), which says which program runs it. Make it executable and run it with its path.
- Create the file./usr/local/bin/hello.sh
#!/bin/bash # hello.sh - first script echo "Hello, $USER. Today is $(date +%A)." exit 0 - Make it executable and run it.
| Part | Why |
|---|---|
#!/bin/bash | Use bash (not another shell) |
# comment | Explain what the script does |
exit 0 | Tell the caller: success (other numbers = an error) |
تذكّر
Folders in $PATH (like /usr/local/bin or ~/bin) let you start the script by name. Elsewhere use ./name.sh.
Read input and use variables
A variable stores a value: NAME=value (no spaces around =), and $NAME uses it. read gets input from the user. $(command) stores the output of a command.
#!/bin/bash
read -p "Which folder? " DIR
COUNT=$(ls -1 "$DIR" | wc -l)
echo "$DIR has $COUNT entries"./input.sh
Which folder? /etc
/etc has 182 entries- Always put variables in double quotes:
"$DIR". Without quotes, names with spaces break. export NAMEmakes a variable visible for programs the script starts.${NAME:-default}usesdefaultwhen NAME is empty.
Use positional parameters
Arguments after the script name arrive as $1, $2 … The script can check how many it got.
| Variable | Contains |
|---|---|
$0 | The script name |
$1 … $9, ${10} | The arguments |
$# | The number of arguments |
"$@" | All arguments, each one separate |
$? | Exit status of the last command |
$$ | PID of the script |
#!/bin/bash
# usage: adduser.sh NAME [GROUP]
if [ $# -lt 1 ]; then
echo "usage: $0 NAME [GROUP]" >&2
exit 1
fi
useradd -G "${2:-users}" "$1" && echo "user $1 created"Use tests and if then else
if runs commands only when a test succeeds (exit status 0). test or [ … ] checks files, strings and numbers.
#!/bin/bash
FILE=$1
if [ -f "$FILE" ]; then
echo "$FILE is a file"
elif [ -d "$FILE" ]; then
echo "$FILE is a folder"
else
echo "$FILE does not exist"
fi| Test | True when |
|---|---|
-f FILE, -d DIR, -e PATH | File / folder / anything exists |
-r, -w, -x FILE | Readable / writable / executable |
-z "$S", -n "$S" | String empty / not empty |
"$A" = "$B", "$A" != "$B" | Strings equal / not equal |
$X -eq $Y, -ne, -lt, -le, -gt, -ge | Numbers: equal, not equal, less, less/equal, greater, greater/equal |
! | Not |
انتبه
Spaces are needed inside the brackets: [ -f "$FILE" ], not [-f "$FILE"].
Use && and ||
A && B runs B only when A worked. A || B runs B only when A failed. Good for short checks.
Repeat with for
for runs the same commands for each item of a list: words, files, numbers or command output.
#!/bin/bash
for USER in anna bob carol; do
useradd "$USER"
done
for FILE in /var/log/*.log; do
echo "$FILE: $(wc -l < "$FILE") lines"
done
for i in {1..5}; do
echo "round $i"
done
for HOST in $(cat hosts.txt); do
ping -c1 -W1 "$HOST" >/dev/null && echo "$HOST up"
doneRepeat with while and until
while repeats while a test is true; until repeats until it becomes true. while read reads a file line by line.
#!/bin/bash
# wait until the web server answers
until curl -fs http://localhost >/dev/null; do
echo "waiting for httpd..."
sleep 2
done
echo "httpd is up"
# read a list line by line
while read -r NAME GROUP; do
useradd -G "$GROUP" "$NAME"
done < users.txtChoose with case
case compares one value with patterns — cleaner than many elif lines. Common for start/stop/status scripts.
#!/bin/bash
case "$1" in
start)
systemctl start httpd ;;
stop)
systemctl stop httpd ;;
status|state)
systemctl status httpd ;;
*)
echo "usage: $0 {start|stop|status}" >&2
exit 1 ;;
esacDebug a script
bash -x prints every command before it runs, with the values filled in. bash -n checks the syntax without running anything.
| Setting | Effect |
|---|---|
set -x / set +x | Trace on / off from this line |
set -e | Stop at the first command that fails |
set -u | Error on unset variables |
set -o pipefail | A pipe fails if any part fails |
في العمل
Start real scripts with set -euo pipefail and check them with shellcheck (from EPEL): it finds quoting bugs and other common mistakes.
نصيحة للامتحان
The exam can ask for a small script: for example "write a script that creates users from a list" or "prints a message based on an argument". Test it with good and bad input, and make it executable.
Remember the main points
The most important facts of this chapter, in short.
- A script starts with
#!/bin/bashand needs execute permission (chmod +x). - Variables:
NAME=value(no spaces), use them as"$NAME";$(command)puts the output of a command in a variable. - Arguments:
$1,$2…, all with"$@", the number with$#;$?is the exit code of the last command. if [ test ]; then … elif …; else …; fichecks conditions;test/[ ]compares numbers (-eq,-gt), text (=,-z) and files (-f,-d,-e).&&runs the next command only on success,||only on failure.- Loops:
for x in LIST; do …; done,while CONDITION; do …; done,until. case "$1" in start) … ;; stop) … ;; *) … ;; esacpicks one of many choices.- Debug with
bash -x script.sh; end withexit 0(ok) or another number (error).
Learn the key terms
The words of this chapter in simple English.
| Term | Meaning |
|---|---|
| Shebang | The first line #!/bin/bash: which program runs the script. |
| Variable | A name that holds a value. |
| Positional parameter | An argument of the script: $1, $2 … |
| Exit code | The number a command returns: 0 = ok, other = error. |
| Command substitution | $(cmd): the output of a command used as a value. |
| Condition | A test that is true or false. |
| Loop | Code that runs many times. |
| Here document | Text inside the script given to a command with <<EOF. |
Check what you learned
Think about the answer first, then open it.
1What must the first line of a Bash script be?
#!/bin/bash.
2How do you check in a script that the user gave at least one argument?
if [ $# -lt 1 ]; then echo "usage: $0 NAME"; exit 1; fi.
3How do you put today's date in a variable?
TODAY=$(date +%F).
4How do you test if /etc/hosts is a normal file?
5Write a loop that creates the users anna, bob and carl.
for u in anna bob carl; do useradd "$u"; done.
6How do you see the exit code of the last command?
7How do you see every line a script runs, for debugging?
bash -x script.sh (or set -x inside the script).
8Why do you write "$1" with quotes?
So a value with spaces stays one argument.