Bash برای Oracle DBAها — بخش ۴: Exit Status و مدیریت خطا در Bash
در اسکریپتهای Oracle DBA و بهویژه در اسکریپتهای Audit و Remediation، مدیریت خطا یک امر حیاتی است. تصور کنید اسکریپتی در حال اجرای یک مرحله حساس است و یک command در آن شکست میخورد؛ اگر اسکریپت این شکست را تشخیص ندهد، ممکن است ادامه دهد و باعث خرابی بیشتر شود یا نتیجه نادرستی را گزارش دهد.
این مقاله به مبحث مهم Exit Status (وضعیت خروج) commandها و نحوهی استفاده از آن برای مدیریت خطاها، ترکیب شرطها با && و ||، و دستورات کنترلی مانند set -e، set -u و set -o pipefail میپردازد.
۱) Exit Status چیست؟
هر command یا اسکریپتی که در لینوکس اجرا میشود، پس از اتمام یک Exit Status (یا return code) برمیگرداند. این عدد نشاندهنده نتیجه اجرای command است:
0: نشاندهنده موفقیت (SUCCESS).- عدد غیر صفر (معمولاً بین ۱ تا ۲۵۵): نشاندهنده خطا (FAILURE) یا وقوع یک وضعیت خاص.
شما میتوانید Exit Status آخرین command اجرا شده را با استفاده از متغیر ویژه $? مشاهده کنید:
ls /tmp
echo $? # اگر /tmp وجود داشته باشد، خروجی 0 خواهد بود
ls /nonexistent_directory
echo $? # اگر مسیر وجود نداشته باشد، خروجی غیر صفر خواهد بود
۲) بررسی Exit Status با if
همانطور که در مقاله قبل دیدیم، میتوان command را مستقیماً داخل if قرار داد. Bash به طور خودکار Exit Status command را بررسی میکند:
if systemctl is-active --quiet sshd; then
echo "SSHD is running."
else
echo "SSHD is not running."
fi
این روش خواناتر از گرفتن $? و سپس مقایسه آن با 0 است.
۳) `exit` command
شما میتوانید با دستور exit از اجرای اسکریپت خارج شوید و یک Exit Status مشخص را برگردانید. این کار برای جلوگیری از ادامه اجرای اسکریپت پس از یک خطای مهم ضروری است.
#!/bin/bash
if [[ "$EUID" -ne 0 ]]; then
echo "ERROR: This script must be run as root."
exit 1 # خروج با کد خطا
fi
echo "Running as root. Proceeding..."
# ... rest of the script ...
exit 0 # خروج موفقیتآمیز
اسکریپتهای Audit و Remediation معمولاً با exit 1 در صورت بروز خطای حیاتی متوقف میشوند تا از عواقب ناخواسته جلوگیری کنند.
۴) ترکیب شرطها با && و ||
عملگرهای && (AND) و || (OR) در Bash فقط برای ترکیب شرطها نیستند؛ بلکه میتوانند commandها را نیز زنجیر کنند.
&& (AND): Command دوم فقط در صورتی اجرا میشود که Command اول با موفقیت (Exit Status 0) تمام شود.
# Run command B only if command A succeeds
command_A && command_B
|| (OR): Command دوم فقط در صورتی اجرا میشود که Command اول با خطا (Exit Status غیر صفر) تمام شود.
# Run command B only if command A fails
command_A || command_B
این الگوها برای اجرای مراحل متوالی یا جایگزین بسیار مفید هستند:
# Example: Backup Oracle config file, and if it fails, report error and exit.
cp "$SSH_CONFIG" "$SSH_CONFIG.bak" && echo "Backup created." || { echo "ERROR: Failed to backup."; exit 1; }
۵) `set -e` (Exit Immediately on Error)
دستور set -e باعث میشود Bash در صورت اجرای هر command با Exit Status غیر صفر، بلافاصله از اسکریپت خارج شود.
#!/bin/bash
set -e # Exit immediately if a command exits with a non-zero status.
echo "Starting script..."
mkdir -p /opt/oracle_data/backup
cp /path/to/config.ora /opt/oracle_data/backup/
echo "Success."
نکته مهم: set -e با شرطهای if، && و || تداخل ندارد؛ یعنی اگر خطایی در بدنه یک شرط بررسی شود، باعث خروج کل اسکریپت نمیشود.
۶) `set -u` (Treat Unset Variables as Error)
دستور set -u باعث میشود Bash در صورت استفاده از یک متغیر تعریف نشده (unset variable) با خطا مواجه شده و اسکریپت را متوقف کند.
#!/bin/bash
set -u
echo "Oracle Home is: $ORACLE_HOME" # اگر تنظیم نباشد، اسکریپت اینجا متوقف میشود.
۷) `set -o pipefail` (Pipeline Failure)
به طور پیشفرض، اگر در یک pipe (مانند A | B)، دستور اول شکست بخورد اما دستور دوم موفق شود، کد نهایی موفقیت (0) گزارش میشود. set -o pipefail تضمین میکند که اگر هر بخشی از pipe شکست بخورد، کل pipe شکست خورده در نظر گرفته شود.
set -o pipefail
cat non_existent_file | grep "pattern"
echo $? # خروجی غیر صفر خواهد بود (خطای cat شناسایی شد)
۸) ترکیب طلایی: `set -euo pipefail`
در اسکریپتهای حرفهای Hardening، هر سه این گزینهها در ابتدا فعال میشوند تا "Strict Mode" ایجاد شود:
#!/bin/bash
set -euo pipefail
# Your robust code here...
۹) جمعبندی
مدیریت خطا در Bash یعنی اجازه ندهیم اسکریپت در وضعیت "نامشخص" به کار خود ادامه دهد. با استفاده از Exit Status و تنظیمات set، اسکریپتهای شما قابل اعتمادتر و خطایابی آنها سادهتر خواهد بود.
مقاله قبلی: Bash برای Oracle DBAها — بخش ۳: بررسی فایلها و دایرکتوریها در Bash
مقاله بعدی: Bash برای Oracle DBAها — بخش ۵: حلقهها و پردازش لیستها در Bash