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 extensionA dialplan entry that matches a dialed number or pattern within a context and triggers a sequence of prioritized steps. lines that appear before any contextA named section of the dialplan that groups extensions. Calls enter a specific context and can only reach extensions visible from it, making contexts the basic unit of call routing and security. 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), trunkA connection between Asterisk and another PBX or an ITSP/carrier, used to send and receive external calls. registrations, and endpointIn PJSIP configuration, the SIP entity Asterisk communicates with: a phone, trunk, or other user agent. Defined by an endpoint section in pjsip.conf. 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.