Safe Reload with Validation
Safe Reload with Validation
Never run asterisk -rx "core reload" blind. This script performs basic config file checks, shows a diff of what changed, performs module-specific reloads (checking each for errors), and verifies post-reload health.
Usage
# Validate and reload
sudo ./safe-reload.sh
# Validate only (dry run)
sudo ./safe-reload.sh --check
Script
#!/bin/bash
set -euo pipefail
ASTERISK="/usr/sbin/asterisk"
CONF_DIR="/etc/asterisk"
CHECK_ONLY=false
if [ "${1:-}" = "--check" ]; then
CHECK_ONLY=true
fi
echo "=== Asterisk Safe Reload ==="
echo ""
# 1. Check that Asterisk is running
if ! ${ASTERISK} -rx "core show version" >/dev/null 2>&1; then
echo "ERROR: Asterisk is not running or not reachable"
exit 1
fi
# 2. Check config files for common syntax problems
echo "Checking config file syntax..."
SYNTAX_ERRORS=0
for CONF_FILE in extensions.conf pjsip.conf voicemail.conf queues.conf; do
if [ ! -f "${CONF_DIR}/${CONF_FILE}" ]; then
continue
fi
# Unclosed section headers: lines starting with [ that don't end with ] or )
# Handles both [context] and [endpoint](template) forms
BAD_BRACKETS=$(grep -n '^\[' "${CONF_DIR}/${CONF_FILE}" \
| grep -v '[])]\s*$' | head -3 || true)
if [ -n "${BAD_BRACKETS}" ]; then
echo " WARNING: Possible unclosed section header in ${CONF_FILE}:"
echo "${BAD_BRACKETS}" | sed 's/^/ /'
SYNTAX_ERRORS=$((SYNTAX_ERRORS + 1))
fi
# Orphaned extension lines before any context header
FIRST_CONTEXT=$(grep -n '^\[' "${CONF_DIR}/${CONF_FILE}" | head -1 | cut -d: -f1 || true)
if [ -n "${FIRST_CONTEXT}" ]; then
ORPHANS=$(head -n "$((FIRST_CONTEXT - 1))" "${CONF_DIR}/${CONF_FILE}" \
| grep -n '^exten\s*=>' | head -3 || true)
if [ -n "${ORPHANS}" ]; then
echo " WARNING: Extension lines before first context in ${CONF_FILE}:"
echo "${ORPHANS}" | sed 's/^/ /'
SYNTAX_ERRORS=$((SYNTAX_ERRORS + 1))
fi
fi
done
if [ "${SYNTAX_ERRORS}" -gt 0 ]; then
echo " Found ${SYNTAX_ERRORS} warning(s) -- review before reloading"
else
echo " OK: No obvious syntax issues"
fi
# 3. Show current state for comparison
echo ""
echo "Current state:"
ENDPOINT_COUNT=$(${ASTERISK} -rx "pjsip show endpoints" 2>&1 | grep -c "Endpoint:" || true)
echo " ${ENDPOINT_COUNT} PJSIP endpoints loaded"
EXTENSION_COUNT=$(${ASTERISK} -rx "dialplan show" 2>&1 | tail -1)
echo " ${EXTENSION_COUNT}"
# 4. Show recent config changes (if git is available)
if command -v git >/dev/null 2>&1 && [ -d "${CONF_DIR}/.git" ]; then
echo ""
echo "Recent config changes:"
(cd "${CONF_DIR}" && git diff --stat HEAD 2>/dev/null | sed 's/^/ /' || true)
echo ""
fi
if ${CHECK_ONLY}; then
echo ""
echo "Dry run complete. No reload performed."
exit 0
fi
# 5. Module-specific reloads with error checking
echo ""
echo "Reloading modules..."
RELOAD_FAILED=false
for MODULE in "dialplan" "pjsip" "voicemail"; do
OUTPUT=$(${ASTERISK} -rx "${MODULE} reload" 2>&1 || true)
if echo "${OUTPUT}" | grep -qi "error\|unable\|failed"; then
echo " FAIL: ${MODULE} reload reported errors:"
echo "${OUTPUT}" | grep -i "error\|unable\|failed" | head -3 | sed 's/^/ /'
RELOAD_FAILED=true
else
echo " OK: ${MODULE} reloaded"
fi
done
if ${RELOAD_FAILED}; then
echo ""
echo "WARNING: One or more modules reported errors during reload."
echo "Check the Asterisk CLI for details: asterisk -rvvv"
fi
# 6. Post-reload health check
sleep 2
echo ""
echo "Post-reload verification:"
ACTIVE_CHANNELS=$(${ASTERISK} -rx "core show channels count" 2>&1 | grep "active call" || echo " 0 active calls")
echo " ${ACTIVE_CHANNELS}"
REG_STATUS=$(${ASTERISK} -rx "pjsip show registrations" 2>&1 | grep -c "Registered" || true)
echo " ${REG_STATUS} trunk registration(s) active"
NEW_ENDPOINT_COUNT=$(${ASTERISK} -rx "pjsip show endpoints" 2>&1 | grep -c "Endpoint:" || true)
echo " ${NEW_ENDPOINT_COUNT} PJSIP endpoints loaded (was ${ENDPOINT_COUNT})"
echo ""
echo "Reload complete."
How it works
- File-level syntax checks: Scans config files for common structural problems: unclosed section headers (handling both
[context]and[endpoint](template)forms) and extension lines that appear before any context header. These checks catch typos that would cause Asterisk to silently ignore config. - Module-specific reloads: Instead of
core reload(which reloads everything at once), the script reloadsdialplan,pjsip, andvoicemailindividually and checks each module's output for errors. This makes it clear which module has a problem if something goes wrong. - Git diff integration: If your
/etc/asteriskis a git repo (highly recommended), the script shows what files changed since the last commit so you can review before reloading. - Post-reload health check: After reload, verifies Asterisk is still healthy: active channels (existing calls survived), trunk registrations, and endpoint count compared to pre-reload.
Tips
- Put
/etc/asteriskunder git version control:cd /etc/asterisk && git init && git add -A && git commit -m "initial". Commit after every change. - Add this script as a git post-commit hook for automatic validation after every config edit.
- For full syntax validation, Asterisk does not provide a dry-run mode. The file-level checks catch common mistakes, but the definitive test is the reload itself.
- In production, consider adding a rollback mechanism: snapshot the config before reload, and if the health check fails, restore and reload again.
User Notes
Know a tip or gotcha for this topic? Share it below and help others.
Contribute a note
Share a tip, gotcha, or practical example. Keep it under 2000 characters. No questions (use the Asterisk community forums for support). Wrap code in backticks.