در قسمت قبل ما با حلقه while آشنا شدیم
تا اینجا اسکریپتهای ما معمولاً به شکل خطی (linear) نوشته شدهاند.
اما وقتی اسکریپت بزرگتر میشود — مثلاً برای:
- System Health Check
- Hardening Check
- Backup Monitoring
نوشتن همه چیز پشت سر هم باعث میشود اسکریپت:
- خوانایی کمی داشته باشد
- نگهداری آن سخت شود
- نتوانیم بخشهای مختلف را دوباره استفاده کنیم
راه حل این مشکل استفاده از توابع (Functions) در Bash است.
تابع در Bash چیست؟
تابع مجموعهای از دستورات است که میتوان آن را چندین بار فراخوانی کرد.
ساختار ساده:
function_name() {
commands
}
مثال:
say_hello() {
echo "Hello"
}
say_hello
مثال واقعیتر
فرض کنید در اسکریپت چند بار نیاز داریم تاریخ و زمان را چاپ کنیم.
بدون تابع:
echo "[$(date)] Starting script"
echo "[$(date)] Checking files"
echo "[$(date)] Script finished"
با تابع:
log_time() {
echo "[$(date)] $1"
}
log_time "Starting script"
log_time "Checking files"
log_time "Script finished"
اینجا:
$1
پارامتر اول تابع است.
پارامترهای تابع
در Bash پارامترهای تابع دقیقاً مثل پارامترهای اسکریپت هستند.
$1
$2
$3
مثال:
check_file() {
if [[ -f "$1" ]]; then
echo "File exists: $1"
else
echo "File not found: $1"
fi
}
check_file /etc/passwd
در اینجا:
$1 = /etc/passwd
مقدار بازگشتی تابع
در Bash توابع با دستور return یک کد وضعیت (exit status) برمیگردانند.
مثال:
check_file() {
if [[ -f "$1" ]]; then
return 0
else
return 1
fi
}
check_file /etc/passwd
if [[ $? -eq 0 ]]; then
echo "File exists"
else
echo "File not found"
fi
در لینوکس:
0 = موفق
غیر صفر = خطا
استفاده از متغیر local
یکی از اشتباهات رایج در Bash استفاده از متغیرهای global است.
مثال مشکلدار:
check_user() {
user=$1
echo "Checking $user"
}
در این حالت متغیر user در کل اسکریپت قابل دسترسی است.
✅ روش بهتر:
check_user() {
local user=$1
echo "Checking $user"
}
متغیر local فقط داخل تابع قابل استفاده است.
این کار باعث میشود اسکریپت:
- قابل پیشبینیتر
- امنتر
- قابل نگهداریتر
باشد.
مثال واقعی: Health Check Script
فرض کنید میخواهیم چند بررسی مختلف انجام دهیم.
میتوانیم هر کدام را در یک تابع قرار دهیم.
check_disk() {
echo "Checking disk usage..."
df -h
}
check_memory() {
echo "Checking memory..."
free -m
}
check_uptime() {
echo "Checking uptime..."
uptime
}
check_disk
check_memory
check_uptime
این روش ساختار اسکریپت را بسیار مرتبتر میکند.
ترتیب تعریف توابع
در Bash باید توابع قبل از استفاده تعریف شوند.
✅ درست:
say_hello() {
echo "Hello"
}
say_hello
❌ اشتباه:
say_hello
say_hello() {
echo "Hello"
}
مثال کوچک واقعی برای DBA
اسکریپتی که وضعیت چند سرویس مهم را بررسی میکند:
check_service() {
local service=$1
if systemctl is-active --quiet "$service"; then
echo "$service is running"
else
echo "$service is NOT running"
fi
}
check_service sshd
check_service crond
check_service rsyslog
این الگو در بسیاری از اسکریپتهای monitoring و automation استفاده میشود.
تمرین
یک تابع بنویسید که:
- یک مسیر به عنوان پارامتر بگیرد
- بررسی کند دایرکتوری وجود دارد یا نه
- اگر وجود داشت تعداد فایلهای آن را چاپ کند
مثال: