دليل

سكريبت bash للمبتدئين: أول سكريبت والمتغيرات والشروط والحلقات وcron

آخر تحديث: · Skillaria.Top

سكريبت Bash ملف نصي يحتوي على أوامر الواجهة، يبدأ سطره الأول بـ #!/bin/bash، ويحصل على صلاحية التشغيل عبر chmod +x ويُشغَّل بالشكل ./script.sh. تُستخدم في السكريبتات المتغيرات والوسائط $1 و$2 وشروط if والحلقات for وwhile، ويُضبط التشغيل الدوري عبر crontab -e.

سكريبت Bash ملف نصي عادي يحتوي على أوامر كنت ستكتبها في الطرفية واحدةً تلو الأخرى. يبدأ السكريبت بسطر shebang وهو #!/bin/bash، ويحصل على صلاحية التنفيذ عبر chmod +x، ويُشغَّل بالشكل ./script.sh. هذا الدليل مخصص للمبتدئين في سكريبتات bash، من السطر الأول حتى التشغيل المجدول: المتغيرات، والوسائط، والشروط، والحلقات، ومعالجة الأخطاء، وcron.

أول سكريبت bash في دقيقة

أنشئ الملف بأي محرر، مثل nano:

nano hello.sh
#!/bin/bash
# أول سكريبت: تحية ومعلومات بسيطة عن النظام
echo "مرحباً، $USER!"
echo "التاريخ اليوم: $(date +%Y-%m-%d)"
echo "أنت الآن في: $(pwd)"

احفظ الملف (Ctrl+O ثم Enter ثم Ctrl+X)، ثم امنحه صلاحية التشغيل وشغّله:

$ chmod +x hello.sh
$ ./hello.sh
مرحباً، alice!
التاريخ اليوم: 2026-10-12
أنت الآن في: /home/alice

الأسطر التي تبدأ بـ # تعليقات. والصيغة $(أمر) تضع مخرجات الأمر داخل النص مباشرةً.

Shebang: دور السطر الأول

يخبر السطر #!/bin/bash النظام بالمفسّر الذي يُنفّذ الملف. وبدونه يُشغَّل السكريبت بأي واجهة متاحة، وفي بعض الأنظمة يكون /bin/sh ليس bash بل dash الأبسط، وعندها لا تعمل بعض التراكيب.

وكثيراً ما يُستخدم أيضاً السطر #!/usr/bin/env bash: يبحث عن bash في PATH، وهذا مفيد إذا كان bash مثبتاً في مكان غير /bin.

كيف تشغّل السكريبت، ولماذا ./

هناك طريقتان:

  • ./hello.sh: يحتاج إلى سطر shebang وإلى صلاحية التنفيذ x. والبادئة ./ ضرورية لأن المجلد الحالي غير موجود في PATH.
  • bash hello.sh: لا يحتاج إلى صلاحية التنفيذ، لأن المفسّر محدد صراحةً.

إذا ظهرت لك رسالة command not found دون ./، وPermission denied دون chmod +x، فهذان هما السببان بالضبط. ولاستدعاء سكريبتاتك بالاسم من أي مكان، ضعها في ~/bin أو /usr/local/bin.

المتغيرات

يُعطى المتغير دون مسافات حول علامة =، ويُقرأ بالرمز $:

#!/bin/bash
name="backup"
dir="/var/backups"
today=$(date +%F)

echo "الملف: ${dir}/${name}-${today}.tar.gz"

الأقواس المعقوفة تفصل اسم المتغير عن النص الذي يليه. أما name = "backup" مع المسافات فخطأ: سيحاول bash تشغيل أمر اسمه name.

علامات الاقتباس مهمة

داخل علامات الاقتباس المزدوجة تُستبدل المتغيرات، أما داخل المفردة فلا. ويُفضَّل دائماً وضع المتغيرات بين علامات مزدوجة، وإلا فإن اسم الملف الذي يحتوي على مسافة سيتحول إلى وسيطين.

file="تقرير مهم.txt"
rm $file      # خطأ: سيحاول حذف «تقرير» و«مهم.txt»
rm "$file"    # صحيح
echo '$HOME'  # يطبع $HOME حرفياً
echo "$HOME"  # يطبع /home/alice

متغيرات البيئة

المتغيرات مثل $HOME و$USER و$PATH يحددها النظام. ويمكن تمرير متغيرك الخاص إلى العمليات الفرعية عبر export. أما إعدادات البيئة الدائمة فتُكتب في ~/.bashrc أو ~/.profile.

وسائط السكريبت

القيم التي تُمرَّر عند التشغيل متاحة في $1 و$2 وهكذا.

المتغيرالمحتوى
$0اسم السكريبت
$1، $2…الوسيط الأول والثاني
$#عدد الوسائط
"$@"جميع الوسائط كل واحدة على حدة
$?رمز إنهاء آخر أمر
$$معرّف العملية PID للسكريبت الحالي
#!/bin/bash
echo "السكريبت $0 تلقّى $# وسيط(وسائط)"
echo "الأول: $1"
$ ./args.sh nginx 80
السكريبت ./args.sh تلقّى 2 وسيط(وسائط)
الأول: nginx

يُقرأ إدخال المستخدم بالأمر read: read -p "أدخل الاسم: " name.

الشرط if

يُعيد كل أمر رمز إنهاء: 0 للنجاح، وأي قيمة أخرى للخطأ. وتفحص العبارة if هذا الرمز تحديداً. وللمقارنات نستخدم عادةً [[ ... ]]، ولا بد من المسافات داخل الأقواس.

#!/bin/bash
if [[ $# -eq 0 ]]; then
    echo "الاستخدام: $0 <مجلد>"
    exit 1
fi

if [[ -d "$1" ]]; then
    echo "المجلد $1 موجود"
elif [[ -f "$1" ]]; then
    echo "$1 ملف، وليس مجلداً"
else
    echo "$1 غير موجود"
fi
الفحصالمعنى
-f fileالملف العادي موجود
-d dirالمجلد موجود
-e pathالمسار موجود
-x fileالملف قابل للتنفيذ
-z "$var" / -n "$var"النص فارغ / غير فارغ
"$a" == "$b"، !=مقارنة النصوص
-eq -ne -lt -le -gt -geمقارنة الأرقام

يمكن أيضاً فحص نتيجة أي أمر مباشرةً:

if systemctl is-active --quiet nginx; then
    echo "nginx يعمل"
else
    echo "nginx متوقف"
fi

وعند وجود خيارات كثيرة يكون case أنسب:

case "$1" in
    start)   echo "تشغيل" ;;
    stop)    echo "إيقاف" ;;
    *)       echo "أمر غير معروف: $1"; exit 1 ;;
esac

الحلقتان for وwhile

for: المرور على قائمة

for host in web1 web2 db1; do
    echo "أفحص $host"
    ping -c 1 -W 1 "$host" > /dev/null && echo "  متاح" || echo "  غير متاح"
done

for file in /var/log/*.log; do
    echo "$file: $(wc -l < "$file") سطر"
done

for i in {1..5}; do
    echo "المحاولة $i"
done

while: ما دام الشرط صحيحاً

المثال الكلاسيكي هو قراءة ملف سطراً بسطر:

while read -r user; do
    echo "المستخدم: $user"
done < users.txt

وانتظار اكتمال تشغيل الخدمة:

count=0
until curl -sf http://localhost:8080/health > /dev/null; do
    count=$((count + 1))
    if [[ $count -ge 10 ]]; then
        echo "لم تبدأ الخدمة"
        exit 1
    fi
    sleep 3
done
echo "الخدمة جاهزة"

تُكتب العمليات الحسابية في bash بين قوسين مزدوجين: $((a + b)). وهي تعمل مع الأعداد الصحيحة فقط.

الدوال

يُنقل الكود المتكرر إلى دوال. وتستخدم الدالة الوسائط نفسها $1 و$2، ويمنع local المتغير من التسرب إلى خارج الدالة.

log() {
    local level="$1"; shift
    echo "$(date '+%F %T') [$level] $*"
}

log INFO "بدء النسخ الاحتياطي"
log ERROR "لا توجد مساحة كافية على القرص"

معالجة الأخطاء: set -euo pipefail

افتراضياً يواصل bash التنفيذ بعد فشل أمر، فقد ينتهي سكريبت النسخ الاحتياطي «بنجاح» دون أن ينسخ شيئاً. لذلك يُضاف في بداية السكريبتات وضع صارم:

#!/bin/bash
set -euo pipefail
  • -e: التوقف عند أول خطأ.
  • -u: اعتبار الإشارة إلى متغير غير معرّف خطأً (يحمي من تنفيذ rm -rf "$DIR/" عندما يكون DIR فارغاً).
  • -o pipefail: يُعدّ الأنبوب فاشلاً إذا فشل أي جزء فيه.

للتصحيح شغّل السكريبت بالأمر bash -x script.sh، فيطبع bash كل أمر قبل تنفيذه. ولاكتشاف الأخطاء الشائعة قبل التشغيل تساعد أداة shellcheck.

مثال عملي: سكريبت نسخ احتياطي

#!/bin/bash
set -euo pipefail

SRC="${1:-/var/www}"
DST="/var/backups/site"
KEEP_DAYS=7
STAMP=$(date +%F_%H-%M)

mkdir -p "$DST"
tar -czf "$DST/site-$STAMP.tar.gz" -C "$(dirname "$SRC")" "$(basename "$SRC")"
echo "تم إنشاء الأرشيف $DST/site-$STAMP.tar.gz"

# حذف الأرشيفات الأقدم من KEEP_DAYS يوماً
find "$DST" -name "site-*.tar.gz" -mtime +"$KEEP_DAYS" -delete

تعني الصيغة ${1:-/var/www}: «استخدم الوسيط الأول، وإذا لم يوجد فاستخدم /var/www». احفظ السكريبت باسم /usr/local/bin/backup-site.sh واجعله قابلاً للتنفيذ: sudo chmod +x /usr/local/bin/backup-site.sh.

التشغيل المجدول: cron

cron خدمة تشغّل الأوامر وفق جدول زمني. تُحرَّر مهام المستخدم بالأمر crontab -e، وتُعرض بالأمر crontab -l، أما مهام root فتُحرَّر بالأمر sudo crontab -e.

يتكون سطر المهمة من خمسة حقول زمنية ثم الأمر:

# الدقيقة الساعة يوم_الشهر الشهر يوم_الأسبوع الأمر
30 2 * * * /usr/local/bin/backup-site.sh >> /var/log/backup.log 2>&1
الجدولوقت التشغيل
*/5 * * * *كل 5 دقائق
0 * * * *في بداية كل ساعة
30 2 * * *كل يوم الساعة 02:30
0 9 * * 1-5أيام العمل الساعة 09:00
0 3 1 * *في اليوم الأول من كل شهر الساعة 03:00
@rebootمرة واحدة بعد الإقلاع

لماذا يعمل السكريبت يدوياً ولا يعمل في cron

  • بيئة مختلفة.تعمل cron بالمتغير PATH المحدود، ولا تقرأ الملف ~/.bashrc. استخدم المسارات الكاملة للأوامر والملفات، أو عرّف PATH في بداية crontab.
  • مجلد عمل مختلف.تبدأ المهمة من المجلد الشخصي وليس من مكان السكريبت. استخدم المسارات المطلقة.
  • علامة %.في crontab تعني % سطراً جديداً، لذلك يجب كتابة date +%F داخل سطر المهمة على الشكل \%. والأسهل نقل الأمر إلى السكريبت.
  • ضياع المخرجات.وجّه المخرجات إلى سجل (>> file 2>&1)، وإلا فلن ترى الأخطاء. وتظهر عمليات cron في journalctl -u cron (وفي أنظمة RHEL اسم الخدمة crond).

في الأنظمة التي تستخدم systemd يمكن استخدام مؤقتات systemd بديلاً عن cron: فهي تكتب المخرجات في السجل، وتستطيع تعويض التشغيلات الفائتة.

الخلاصة

سكريبت Bash للمبتدئين هو ملف يبدأ بالسطر #!/bin/bash، ويحصل على صلاحية التشغيل، ويحتوي على سلسلة من الأوامر. ضع المتغيرات بين علامات اقتباس، وتحقق من الوسائط عبر if، واستخدم الحلقتين for وwhile، وفعّل الوضع الصارم set -euo pipefail، فتحصل على أداة أتمتة موثوقة يشغّلها cron وفق الجدول. وتُشرح سكريبتات bash والبيئة وcron عملياً في دورة لينكس.

الأسئلة الشائعة

ما الفرق بين bash وsh؟

sh هو الواجهة القياسية POSIX، وbash نسخة موسعة منها تضيف المصفوفات والأقواس المزدوجة ومزايا أخرى. السكريبت الذي يستخدم صيغ bash يجب أن يُشغَّل بـ bash، لا بـ sh.

ما امتداد ملف سكريبت bash؟

لا يهتم لينكس بالامتداد، فالمفسّر يُحدَّد بسطر shebang. الامتداد .sh مجرد عرف يسهّل معرفة أن الملف سكريبت.

كيف أمرر كلمة مرور إلى السكريبت بأمان؟

لا تمررها كوسيط، لأن الوسائط تظهر لباقي المستخدمين في الأمر ps. استخدم متغير بيئة من ملف صلاحيته 600، أو استخدم read -s للإدخال دون إظهار النص.

كيف أتحقق من أن السكريبت يعمل بصلاحيات root؟

قارن معرّف المستخدم بالصفر: if [[ $EUID -ne 0 ]]; then echo "يلزم root"; exit 1; fi.

كيف أشغّل السكريبت في الخلفية كي لا يتوقف بعد الخروج من SSH؟

استخدم nohup ./script.sh &، أو جلسة tmux أو screen، ولتشغيل دائم حوّل السكريبت إلى خدمة systemd.

تعلّم هذا الموضوع بالفيديو

يُشرح هذا الموضوع بالتفصيل مع التطبيق العملي في دورة «Linux: с нуля до уверенного администрирования».

الانتقال إلى الدورة