Bash برای Oracle DBAها — بخش ۶: Command Substitution و Here Docs در Bash
در اسکریپتهای Oracle DBA، خیلی وقتها لازم است خروجی یک command را در یک متغیر ذخیره کنیم، یا چند خط متن را بهصورت مستقیم به یک command یا فایل بدهیم. Bash برای این کار دو ابزار بسیار مهم دارد:
- Command Substitution برای گرفتن خروجی command و استفاده از آن در یک عبارت دیگر؛
- Here Document برای ارسال چند خط متن به یک command یا فایل.
این دو مفهوم در اسکریپتهای Hardening، Audit، Remediation و حتی در اسکریپتهای مرتبط با Oracle بسیار مهم هستند، چون به ما اجازه میدهند داده را از ابزارهای سیستم بگیریم، پردازش کنیم و در قالبی تمیز و قابلفهم استفاده کنیم.
۱) Command Substitution چیست؟
Command substitution یعنی اجرای یک command و جایگزین کردن خروجی آن در همان نقطهای که نوشته شده است. در Bash دو شکل برای آن وجود دارد:
- فرم قدیمی:
`command` - فرم مدرن و توصیهشده:
$(command)
فرم $(...) خواناتر است و nesting هم در آن بهتر انجام میشود. به همین دلیل در اسکریپتهای حرفهای تقریباً همیشه از همین فرم استفاده میشود.
۲) مثال ساده از Command Substitution
current_date=$(date)
echo "Current date is: $current_date"
در این مثال، خروجی command date داخل متغیر current_date ذخیره میشود. این الگو در اسکریپتهای DBA برای ذخیره وضعیت سیستم، نام host، نام database، یا نتیجه یک query بسیار کاربردی است.
۳) Command Substitution در اسکریپتهای واقعی
در فایل audit مربوط به System Crypto Policy، دو نمونه command substitution دیده میشود:
CURRENT_POLICY=$(update-crypto-policies --show 2>/dev/null)
HARDCODED=$(grep -h -E -i '^\s*(Ciphers|MACs|KexAlgorithms|GSSAPIKexAlgorithms|HostKeyAlgorithms|PubkeyAcceptedKeyTypes)' /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf 2>/dev/null)
در خط اول، خروجی update-crypto-policies --show در متغیر CURRENT_POLICY ذخیره میشود. در خط دوم، خروجی grep در متغیر HARDCODED قرار میگیرد تا بعداً بررسی شود آیا تنظیمات hardcoded SSH وجود دارند یا خیر.
این الگو برای Oracle DBAها بسیار آشناست؛ چون دقیقاً مشابه زمانی است که خروجی commandهایی مثل hostname، df، ps یا queryهای SQL*Plus را در یک متغیر ذخیره میکنیم و بعد بر اساس آن تصمیم میگیریم.
۴) چرا $(...) بهتر از backticks است؟
فرم مدرن $(...) چند مزیت مهم دارد:
- خواناتر است؛
- تو در تو کردن آن سادهتر است؛
- در اسکریپتهای پیچیده کمتر خطا ایجاد میکند.
مثال nesting:
echo "User: $(whoami), Home: $(echo "$HOME")"
در backticks، چنین nestingی سختتر و مستعد خطاست.
۵) نکات quoting در Command Substitution
وقتی خروجی command را در متغیر ذخیره میکنید، معمولاً باید هنگام استفاده از آن را داخل double quotes بگذارید:
value=$(some_command)
echo "$value"
اگر از کوتیشن استفاده نکنید، Bash ممکن است بر اساس فاصلهها و tabها مقدار را به چند بخش تقسیم کند. این موضوع در اسکریپتهای DBA که روی مسیرها، نام فایلها یا خروجیهای متنی حساس کار میکنند بسیار مهم است.
۶) Arithmetic Expansion و Command Substitution
در اسکریپتهای audit معمولاً برای شمارش خطاها یا هشدارها از arithmetic expansion استفاده میشود:
FAIL_COUNT=$((FAIL_COUNT + 1))
این مورد command substitution نیست، اما از نظر مفهومی مشابه است چون Bash یک expression را evaluate میکند و نتیجه را جایگزین میسازد. در فایل audit مربوط به crypto policy، این الگو برای افزایش شمارنده خطاها استفاده شده است.
۷) Here Document چیست؟
Here Document یا heredoc روشی است برای ارسال چند خط متن به یک command، فایل یا بلوک ورودی. ساختار کلی آن اینگونه است:
command <
هر چیزی بین <<EOF و خط پایانی EOF بهعنوان ورودی command در نظر گرفته میشود.
۸) Here Document در اسکریپت Remediation
در فایل remediation این ساختار بهصورت زیر دیده میشود:
cat < /etc/crypto-policies/policies/modules/CIS-SSH.pmod
# Disable CBC and ChaCha20-Poly1305 for SSH
cipher@ssh = -*CBC -CHACHA20-POLY1305
# Disable MACs less than 128 bits
mac@ssh = -*MD5* -*UMAC-64*
EOF
اینجا heredoc برای ساخت یک فایل policy استفاده شده است. در واقع Bash متن چندخطی را به cat میدهد و سپس خروجی آن با > در فایل مشخصشده نوشته میشود.
این الگو در اسکریپتهای DBA هم بسیار مفید است؛ مثلاً زمانی که بخواهیم یک فایل configuration، یک SQL script، یا یک policy file را از داخل اسکریپت بسازیم.
۹) Quoting در Here Document
اگر delimiter را quoted نکنید، Bash داخل heredoc را از نظر expansion پردازش میکند. اگر delimiter را quoted کنید، expansion غیرفعال میشود.
cat <<'EOF'
This $variable will not expand.
Neither will $(command).
EOF
این تکنیک زمانی مفید است که بخواهید متن را دقیقاً همانطور که نوشتهاید به فایل یا command بدهید، بدون اینکه Bash متغیرها یا command substitution را پردازش کند.
۱۰) Here Document و Redirect
در مثال remediation، خروجی heredoc مستقیم در یک فایل نوشته میشود:
cat < /path/to/file
content
EOF
این یک الگوی بسیار رایج برای ساخت فایلهای موقت، فایلهای policy، یا حتی SQL scriptهاست.
۱۱) تفاوت Here Doc و Here String
در این بخش فقط heredoc وجود دارد، نه here string. تفاوتشان این است:
- Here Document: چندخطی است و از
<<EOFاستفاده میکند. - Here String: یک رشته تکخطی را با
<<<به command میدهد.
نمونه here string:
grep "oracle" <<< "$text"
در فایلهای بررسیشده، here string استفاده نشده است، اما دانستن تفاوت آن با heredoc مهم است.
۱۲) نکات مهم برای Oracle DBAها
اگرچه این دو اسکریپت مستقیماً به SQL*Plus یا database connection وصل نمیشوند، اما الگوهایشان برای Oracle DBAها بسیار آموزنده است:
- Command substitution برای گرفتن خروجی ابزارهای سیستم یا SQL*Plus؛
- Heredoc برای تولید فایلهای configuration یا script؛
- Quoting صحیح برای جلوگیری از word splitting؛
- Redirectها برای ساخت فایلها یا جمعآوری خروجی.
در کار واقعی DBA، همین الگوها برای ساخت SQL script، ارسال query به database، یا ذخیره خروجی گزارشها استفاده میشوند.
۱۳) جمعبندی
در این بخش یاد گرفتیم که:
$(...)روش استاندارد گرفتن خروجی command است؛- backticks قدیمیتر و کمتر خوانا هستند؛
- heredoc برای تزریق چند خط متن بسیار کاربردی است؛
- quoted delimiter مانع expansion میشود؛
- در اسکریپتهای Hardening و Oracle DBA، این الگوها بسیار رایج و ضروریاند.
در مقاله بعدی به سراغ Functions در Bash میرویم؛ یعنی چطور بلوکهای قابلاستفادهمجدد بسازیم، ورودی بگیریم، خروجی برگردانیم و اسکریپتهای DBA را ساختارمندتر کنیم.
مقاله قبلی: Bash برای Oracle DBAها — بخش ۵: حلقهها و پردازش لیستها در Bash
مقاله بعدی: Bash برای Oracle DBAها — بخش ۷: Functions و استفاده مجدد در Bash