إنشاء قوالب الإعدادات باستخدام envsubst وheredocs
أنشئ إعدادات وقت التشغيل من متغيرات البيئة باستخدام envsubst وheredocs مقتبسة
إنشاء قوالب الإعدادات باستخدام envsubst وheredocs درس مجاني في Linux Command Line & Bash Scripting Mastery على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Linux Command Line & Bash Scripting Mastery، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Linux Command Line & Bash Scripting Mastery 4 دروس في المجموع.
لماذا يهم إنشاء قوالب الإعداد وقت التشغيل
في مسارات DevOps وسير عمل الحاويات، تحتاج ملفات الإعداد مثل nginx.conf وprometheus.yml وdocker-compose.yml غالبًا إلى التغيير بين البيئات، مثل بيئات التجهيز والإنتاج والتعافي من الكوارث. ويؤدي تثبيت القيم داخل الشيفرة إلى اختلاف الإعدادات وانكشاف الأسرار.
الحل هو إنشاء قوالب الإعداد وقت التشغيل: اشحنوا قالبًا يحتوي على عناصر نائبة، ثم أدخلوا القيم الفعلية عند بدء التشغيل من متغيرات البيئة. يحافظ ذلك على عدم قابلية تغيير الصورة، ويجعل إعداداتكم قابلة للتدقيق.
- لا تُضمَّن الأسرار داخل الصور
- يُروَّج للعنصر نفسه عبر البيئات
- يُنشأ الإعداد قبل بدء العملية مباشرةً
تجعل أداتان متكاملتان ذلك أمرًا بسيطًا في Bash: envsubst وheredocs المقتبسة.
envsubst: مولّد الإعدادات بسطر واحد
envsubst أداة GNU صغيرة تقرأ من stdin، وتستبدل العناصر النائبة $VARIABLE و${VARIABLE} بقيمها من البيئة الحالية، ثم تكتب الناتج إلى stdout.
تأتي هذه الأداة مع حزمة gettext، وهي متاحة تقريبًا في جميع توزيعات Linux والصور الأساسية لـ Docker.
- تعمل مع أي تنسيق نصي: NGINX وYAML وTOML وJSON وINI
- لا تقيّم صياغة shell، بل تستبدل مراجع المتغيرات فقط
- آمنة: لا تنفذ الأوامر الموجودة داخل القالب
#!/usr/bin/env bash
# Install check (usually already present)
which envsubst || apt-get install -y gettext-base
# Minimal demo
export APP_PORT=8080
export APP_HOST=api.example.com
echo 'server { listen ${APP_PORT}; server_name ${APP_HOST}; }' | envsubst
# Output: server { listen 8080; server_name api.example.com; }الاستبدال الانتقائي للمتغيرات
تستبدل envsubst افتراضيًا كل $VAR تجده. وقد يؤدي ذلك إلى إفساد متغيرات NGINX مثل $uri أو $host، فهذه توجيهات NGINX حقيقية وليست متغيرات بيئة خاصة بكم.
مرّروا قائمة صريحة بالمتغيرات باعتبارها الوسيط الأول لتقييد الاستبدال على تلك الأسماء فقط:
envsubst '$VAR1 $VAR2'الوسيط عبارة عن سلسلة بين علامتي اقتباس مفردتين، حتى لا يوسّعها shell، وتحتوي على أسماء المتغيرات المطلوب استبدالها، مفصولة بمسافات أو أسطر جديدة.
#!/usr/bin/env bash
export APP_PORT=8080
export APP_HOST=api.example.com
# NGINX template contains both our vars AND nginx vars ($uri, $host)
TEMPLATE='server {
listen ${APP_PORT};
server_name ${APP_HOST};
location / {
proxy_set_header Host $host;
proxy_pass http://backend$uri;
}
}'
# Only substitute APP_PORT and APP_HOST — leave $host and $uri untouched
echo "$TEMPLATE" | envsubst '${APP_PORT} ${APP_HOST}'
ملفات القوالب على القرص
بالنسبة إلى ملفات الإعداد الفعلية، خزّنوا القالب في ملف، مثل nginx.conf.template، إلى جانب ملف Docker. وعند بدء تشغيل الحاوية، شغّلوا envsubst لإنتاج ملف الإعداد النهائي قبل تشغيل الخدمة.
هذا هو النمط القياسي المستخدم في صورة NGINX الرسمية على Docker.
#!/usr/bin/env bash
# File: nginx.conf.template
# (In practice this lives on disk; we write it here for demo purposes)
cat > /tmp/nginx.conf.template << 'TMPL'
server {
listen ${NGINX_PORT};
server_name ${SERVER_NAME};
root /var/www/${APP_ENV};
location / {
proxy_pass http://app:${APP_PORT};
}
}
TMPL
export NGINX_PORT=80
export SERVER_NAME=myapp.example.com
export APP_ENV=production
export APP_PORT=3000
# Generate final config
envsubst '${NGINX_PORT} ${SERVER_NAME} ${APP_ENV} ${APP_PORT}' \
< /tmp/nginx.conf.template \
> /tmp/nginx.conf
cat /tmp/nginx.confمستندات Heredoc مقتبسة: قوالب مضمنة دون ملف مؤقت
يمنع مستند heredoc المقتبس (باستخدام << 'EOF' مع وضع المحدِّد بين علامتي اقتباس مفردتين) الصدفةَ من توسيع المتغيرات أو تنفيذ استبدالات الأوامر داخل الكتلة. ويُعامَل المحتوى كسلسلة نصية حرفية.
وهذا يجعل مستندات heredoc الطريقة المثالية لكتابة قالب مضمّن وتمريره مباشرةً إلى envsubst — دون الحاجة إلى ملف وسيط.
<< EOF(غير مقتبس) — توسّع الصدفة$VARفورًا<< 'EOF'(مقتبس) — يكون المحتوى حرفيًا، ويُؤجَّل التوسيع إلىenvsubst
#!/usr/bin/env bash
export DB_HOST=postgres.internal
export DB_PORT=5432
export DB_NAME=myapp_prod
# Quoted heredoc: shell does NOT expand $DB_HOST etc. yet
envsubst << 'EOF'
[database]
host = ${DB_HOST}
port = ${DB_PORT}
dbname = ${DB_NAME}
EOF
# Output uses actual env var values — expansion done by envsubst, not the shellدمج مستندات Heredoc مع إعادة توجيه المخرجات
مرّر مستند heredoc مقتبسًا عبر envsubst وأعد توجيه النتيجة إلى ملف ضمن تعبير واحد. هذه هي الصيغة الأنظف لإنشاء ملفات الإعدادات في برنامج الدخول.
استخدم الاستبدال الانتقائي ('${VAR1} ${VAR2}') عندما تكون للصيغة المستهدفة (Prometheus أو NGINX وغيرهما) بنية $variable خاصة بها وتحتاج إلى حمايتها.
#!/usr/bin/env bash
# entrypoint.sh — Docker container entrypoint
set -euo pipefail
export PROM_PORT=${PROM_PORT:-9090}
export SCRAPE_INTERVAL=${SCRAPE_INTERVAL:-15s}
export TARGET_HOST=${TARGET_HOST:-localhost:8080}
envsubst '${PROM_PORT} ${SCRAPE_INTERVAL} ${TARGET_HOST}' << 'EOF' > /etc/prometheus/prometheus.yml
global:
scrape_interval: ${SCRAPE_INTERVAL}
evaluation_interval: ${SCRAPE_INTERVAL}
scrape_configs:
- job_name: 'app'
static_configs:
- targets: ['${TARGET_HOST}']
EOF
echo "[entrypoint] Prometheus config written on port ${PROM_PORT}"
exec prometheus --config.file=/etc/prometheus/prometheus.yml --web.listen-address=":${PROM_PORT}"القيم الافتراضية والتحقق قبل الاستبدال
لا تفترض أبدًا أن جميع المتغيرات المطلوبة مضبوطة. استخدم توسعة معاملات Bash لتوفير قيم افتراضية أو لإيقاف التنفيذ مع عرض خطأ واضح:
${VAR:-default}— استخدامdefaultإذا لم يكنVARمضبوطًا أو كان فارغًا${VAR:?error message}— إيقاف التنفيذ مع عرض خطأ إذا لم يكنVARمضبوطًا أو كان فارغًا
اضبط هذه القيم قبل استدعاء envsubst، كي يحصل القالب دائمًا على قيمة فعلية أو يتوقف البرنامج مبكرًا مع رسالة مفيدة.
#!/usr/bin/env bash
set -euo pipefail
# Required — abort if missing
: "${DATABASE_URL:?DATABASE_URL must be set}"
: "${SECRET_KEY:?SECRET_KEY must be set}"
# Optional with defaults
export APP_PORT=${APP_PORT:-8000}
export LOG_LEVEL=${LOG_LEVEL:-info}
export WORKERS=${WORKERS:-4}
envsubst '${DATABASE_URL} ${SECRET_KEY} ${APP_PORT} ${LOG_LEVEL} ${WORKERS}' \
< /app/config/app.conf.template \
> /app/config/app.conf
echo "[init] Config generated — port=${APP_PORT} workers=${WORKERS} log=${LOG_LEVEL}"إنشاء إعدادات متعددة الأقسام باستخدام مستندات Heredoc متعددة
بالنسبة إلى ملفات الإعدادات المعقدة المبنية من أقسام منطقية، يمكنك إنشاء كل قسم بشكل مستقل ثم دمج الأقسام، أو استخدام مستند heredoc واحد يمتد على الملف بأكمله. تنجح الطريقتان — فاختر بينهما بناءً على سهولة القراءة.
عندما تُضمَّن الأقسام بشكل مشروط (مثل تضمين كتلة TLS فقط عند ضبط مسار الشهادة)، تكون طريقة heredoc المتعددة مع كتل if أوضح.
#!/usr/bin/env bash
set -euo pipefail
export APP_HOST=${APP_HOST:-localhost}
export APP_PORT=${APP_PORT:-8080}
export TLS_CERT=${TLS_CERT:-}
export TLS_KEY=${TLS_KEY:-}
CONFIG_FILE=/tmp/app.conf
# Base section
envsubst '${APP_HOST} ${APP_PORT}' << 'BASE' > "$CONFIG_FILE"
[server]
host = ${APP_HOST}
port = ${APP_PORT}
BASE
# Conditional TLS section — only appended when cert is provided
if [[ -n "$TLS_CERT" && -n "$TLS_KEY" ]]; then
envsubst '${TLS_CERT} ${TLS_KEY}' << 'TLS' >> "$CONFIG_FILE"
[tls]
cert_file = ${TLS_CERT}
key_file = ${TLS_KEY}
TLS
echo "[init] TLS enabled"
else
echo "[init] TLS disabled (no cert/key provided)"
fi
cat "$CONFIG_FILE"نمط برنامج الدخول في Docker
يستخدم نمط برنامج الدخول الموصى به في Docker برنامجًا نصيًا للصدفة (docker-entrypoint.sh) لإنشاء ملفات الإعدادات عند بدء التشغيل، ثم يسلّم التحكم إلى العملية الرئيسية باستخدام exec. يستبدل استخدام exec عملية الصدفة بعملية الخدمة، لذلك تصل الإشارات (SIGTERM وSIGINT) إلى الخدمة مباشرةً — وهذا ضروري للإيقاف السلس.
تُضاف ملفات القوالب إلى الصورة أثناء البناء، وتُحقن القيم أثناء التشغيل من خلال docker run -e أو env: / envFrom: في Kubernetes.
#!/usr/bin/env bash
# docker-entrypoint.sh
set -euo pipefail
# Validate required env vars
for var in DATABASE_URL REDIS_URL SECRET_KEY; do
: "${!var:?$var is required}"
done
export APP_PORT=${APP_PORT:-8000}
export WORKERS=${WORKERS:-$(nproc)}
echo "[entrypoint] Generating configuration..."
envsubst '${DATABASE_URL} ${REDIS_URL} ${SECRET_KEY} ${APP_PORT} ${WORKERS}' \
< /app/config/settings.toml.template \
> /app/config/settings.toml
echo "[entrypoint] Starting server on port ${APP_PORT} with ${WORKERS} workers"
exec gunicorn app:application \
--bind "0.0.0.0:${APP_PORT}" \
--workers "${WORKERS}"نمط Kubernetes ConfigMap مع envsubst
في Kubernetes، تُحقن متغيرات البيئة عبر env: أو envFrom: في مواصفة Pod. يستدعي برنامج الدخول في الحاوية envsubst لإنشاء ملفات الإعدادات فعليًا قبل بدء العملية — ومن دون الحاجة إلى ConfigMap لكل بيئة.
يُبقي ذلك القيم الخاصة بكل بيئة داخل Secrets وConfigMaps في Kubernetes (للبيانات غير الحساسة)، بينما يبقى قالب الإعدادات داخل الصورة. صورة واحدة، وبيئات متعددة.
- البناء:
COPY nginx.conf.template /etc/nginx/templates/ - وقت التشغيل: يشغّل برنامج الدخول
envsubstويكتب إلى/etc/nginx/nginx.conf - يحقن K8s:
APP_PORTوBACKEND_HOSTمن Secret/ConfigMap
تصحيح أخطاء envsubst: العثور على المتغيرات المفقودة أو غير المحلولة
عندما يحتوي ملف الإعدادات المُنشأ على ${VAR} حرفيًا بدلًا من قيمة، فهذا يعني أن المتغير لم يُصدَّر أو لم يُدرج في قائمة الاستبدال. استخدم الأساليب التالية لتصحيح الخطأ:
printenv | sort— سرد جميع المتغيرات المُصدَّرة- مقارنة العناصر النائبة في القالب بالمتغيرات المُصدَّرة باستخدام
grep - تشغيل
envsubstثم البحث في المخرجات عن أنماط${المتبقية - استخدام
set -uفي البرنامج النصي المستدعي، كي تؤدي مراجع المتغيرات غير المضبوطة في كود Bash إلى الإيقاف فورًا
#!/usr/bin/env bash
set -euo pipefail
TEMPLATE=/tmp/app.conf.template
OUTPUT=/tmp/app.conf
# Write a demo template
cat > "$TEMPLATE" << 'EOF'
host=${DB_HOST}
port=${DB_PORT}
name=${DB_NAME}
EOF
export DB_HOST=db.internal
export DB_PORT=5432
# DB_NAME intentionally left unset
envsubst < "$TEMPLATE" > "$OUTPUT"
# Detect unresolved placeholders
if grep -qE '\$\{[A-Z_]+\}' "$OUTPUT"; then
echo "ERROR: unresolved placeholders found:"
grep -oE '\$\{[A-Z_]+\}' "$OUTPUT" | sort -u
exit 1
fi
echo "Config OK:"
cat "$OUTPUT"اختبار المعرفة: الاستبدال الانتقائي في envsubst
افترض أن قالب إعدادات NGINX يحتوي على متغير التطبيق ${APP_PORT} ومتغير NGINX الأصلي $uri معًا. شغّل الأمر التالي:
envsubst < nginx.conf.template > nginx.conf
ما النتيجة؟
مراجعة الدرس: إنشاء قوالب الإعدادات باستخدام envsubst وHeredoc
أصبح لديك الآن مجموعة أدوات جاهزة لبيئات الإنتاج لإنشاء إعدادات وقت التشغيل في Bash:
- يستبدل envsubst العناصر النائبة
${VAR}في أي ملف نصي باستخدام البيئة الحالية — دون الحاجة إلى كتابة برامج نصية أو إجراء عمليات هروب خاصة - يحمي الاستبدال الانتقائي (
envsubst '${VAR1} ${VAR2}') المتغيرات الأصلية في NGINX وPrometheus والأدوات المشابهة من الاستبدال غير المقصود - تؤجل مستندات heredoc المقتبسة (
<< 'EOF') توسعة الصدفة، بحيث يصل محتوى القالب إلىenvsubstدون تغيير — ومن دون الحاجة إلى ملفات مؤقتة - تحقق قبل الاستبدال: استخدم
${VAR:?message}لإيقاف التنفيذ عند فقدان المتغيرات المطلوبة، و${VAR:-default}للمتغيرات الاختيارية - نمط برنامج الدخول في Docker: أنشئ الإعدادات عند بدء الحاوية، ثم استخدم
execلتشغيل الخدمة كي تُعالَج الإشارات بشكل صحيح - صحّح العناصر النائبة غير المحلولة بالبحث في المخرجات عن أنماط
${المتبقية قبل بدء العملية
تحافظ هذه الأنماط على ثبات صور الحاويات، وتُبقي الأسرار خارج نظام التحكم في الإصدارات، وتضمن اتساق ملفات الإعدادات عبر جميع البيئات.
الأسئلة الشائعة
هل درس «إنشاء قوالب الإعدادات باستخدام envsubst وheredocs» مجاني؟
نعم — نص درس «إنشاء قوالب الإعدادات باستخدام envsubst وheredocs» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Linux Command Line & Bash Scripting Mastery، انتقل إلى CoddyKit PRO. تتضمن دورة Linux Command Line & Bash Scripting Mastery 4 دروس في المجموع.
ماذا ستتعلم في «إنشاء قوالب الإعدادات باستخدام envsubst وheredocs»؟
أنشئ إعدادات وقت التشغيل من متغيرات البيئة باستخدام envsubst وheredocs مقتبسة تتمرن على Linux Command Line & Bash Scripting Mastery مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Linux Command Line & Bash Scripting Mastery؟
لا تُشترط خبرة سابقة. Linux Command Line & Bash Scripting Mastery على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «إنشاء قوالب الإعدادات باستخدام envsubst وheredocs»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Linux Command Line & Bash Scripting Mastery هذا؟
نعم. كل درس في Linux Command Line & Bash Scripting Mastery يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- كتابة Dockerfiles خفيفة ونقاط دخول Shell
- إنشاء قوالب الإعدادات باستخدام envsubst وheredocs
- برمجة موارد السحابة باستخدام CLI وjq
- فحوصات الصحة وبوابات الجاهزية وحلقات الانتظار