Реализация автоматического исходящего обзвона через Call Files в Asterisk
- Файлы обзвона из папки
/var/spool/asterisk/outgoing/не подхватываются или вызывают зависание Asterisk. - Перегрузка каналов провайдера и отказы
503 Service Unavailableиз-за неконтролируемого сброса сотен .call файлов одновременно. - Ошибки прав доступа (
Permission denied) при перемещении файлов в директорию очереди.
1. Механика работы Asterisk Call Files
Asterisk непрерывно отслеживает каталог /var/spool/asterisk/outgoing/ с помощью механизма inotify. Как только в каталоге появляется файл с правами чтения для пользователя asterisk, ядро инициирует исходящий вызов в канал Channel, а после ответа направляет его в диалплан (Context/Extension) или приложение (Application).
2. Корректный синтаксис файла .call
Channel: PJSIP/89991234567@trunk-provider-a
CallerID: "Notification Service" <88001002030>
MaxRetries: 2
RetryTime: 60
WaitTime: 30
Context: auto-informer
Extension: s
Priority: 1
Set: CUSTOM_CLIENT_ID=54321
Set: AUDIO_FILE=promos/march_sale
Archive: Yes3. Обработка логики информирования в extensions.conf
[auto-informer]
exten => s,1,NoOp(=== Client ${CUSTOM_CLIENT_ID} Answered Auto-Call ===)
same => n,Answer()
same => n,Wait(1)
same => n,Playback(${AUDIO_FILE})
same => n,Read(KEY_PRESSED,press_one_to_connect,1,,,5)
same => n,GotoIf($["${KEY_PRESSED}" = "1"]?connect_manager:bye)
same => n(connect_manager),NoOp(Transferring to Call Center)
same => n,Dial(PJSIP/100,20,tT)
same => n,Hangup()
same => n(bye),Playback(thank-you-goodbye)
same => n,Hangup()
; Обработка неудачных попыток вызова
exten => failed,1,NoOp(=== Auto-Call Failed for ID: ${CUSTOM_CLIENT_ID} with Status: ${REASON} ===)
same => n,System(/usr/local/bin/report_call_fail.sh ${CUSTOM_CLIENT_ID} ${REASON})
same => n,Hangup()4. Shell-скрипт безопасной генерации .call файлов (Атомарность)
Критическое правило: Никогда не создавайте .call файлы напрямую внутри /var/spool/asterisk/outgoing/! Создавайте их во временном каталоге и перемещайте командой mv.
#!/usr/bin/env bash
set -euo pipefail
TEMP_DIR="/tmp/asterisk_calls"
SPOOL_DIR="/var/spool/asterisk/outgoing"
mkdir -p "$TEMP_DIR"
GENERATE_CALL() {
local PHONE="$1"
local CLIENT_ID="$2"
local FILE_NAME="call_${CLIENT_ID}_$(date +%s%N).call"
cat <<EOF > "${TEMP_DIR}/${FILE_NAME}"
Channel: PJSIP/${PHONE}@trunk-provider-a
CallerID: <88001002030>
MaxRetries: 1
RetryTime: 30
WaitTime: 25
Context: auto-informer
Extension: s
Priority: 1
Set: CUSTOM_CLIENT_ID=${CLIENT_ID}
EOF
chown asterisk:asterisk "${TEMP_DIR}/${FILE_NAME}"
# Атомарное перемещение
mv "${TEMP_DIR}/${FILE_NAME}" "${SPOOL_DIR}/"
}
# Пример отправки звонка
GENERATE_CALL "89261112233" "1001" Частые вопросы (FAQ)
Почему Asterisk пытается набрать номер до того, как файл полностью записался?
Если писать файл напрямую в /var/spool/asterisk/outgoing/, inotify ядра Asterisk сработает на событие создания файла и прочитает его полупустым. Поэтому файлы формируются во временной папке /tmp и атомарно перемещаются через команду mv.
Как ограничить количество одновременных звонков при автообзвоне?
Используйте планировщик в вашем внешнем скрипте-генераторе (контроль пула через GROUP_COUNT в диалплане или ограничение количества .call файлов в spool директории).
Как запланировать запуск .call файла на определенное время в будущем?
Измените дату модификации файла утилитой touch перед перемещением в outgoing: touch -d '2025-05-01 10:00:00' /tmp/my_call.call. Asterisk проигнорирует файл, пока системное время не достигнет даты mtime файла.
Что означает статус ${REASON} в ветке failed?
Переменная ${REASON} принимает целочисленные коды: 0 (ошибка канала/не на связи), 1 (абонент сбросил/busy), 3 (таймаут ответа/no answer), 8 (успешное соединение).