Справочник системных ошибок и решений

Windows Server, Active Directory, 1С:Предприятие, СУБД, Linux, Cisco, MikroTik, Asterisk.

⚠️ Важная информация Все материалы, инструкции, команды и скрипты на сайте предоставлены исключительно в ознакомительных целях. Их применение может повлиять на работу операционной системы, программного обеспечения, баз данных, сетевого оборудования и других компонентов инфраструктуры. Перед выполнением действий создайте резервную копию и по возможности протестируйте изменения в безопасной среде. Пользователь самостоятельно оценивает риски и несет ответственность за результат. При отсутствии необходимых знаний обратитесь к квалифицированному ИТ-специалисту.

AGI_SCRIPT_EXEC_FAIL IP-Телефония и СКУД

Разработка сценариев Asterisk AGI на Python, PHP и Node.js: протокол и отладка

Обновлено: 24.08.2026 · Официальная документация ↗
  • Ошибка AGI Script script.php completed, returning -1 и мгновенный разрыв соединения.
  • Asterisk зависает при выполнении AGI команды (Deadlock / Broken Pipe).
  • Скрипт завершается с ошибкой Permission denied или не имеет прав на исполнение.
  • Переменные канала Asterisk не передаются в стороннюю CRM-систему.

1. Архитектура протокола Asterisk Gateway Interface (AGI)

Asterisk запускает AGI-скрипт как дочерний процесс, передавая системные переменные вызова в STDIN. Скрипт отправляет команды ядру Asterisk через STDOUT и получает результат выполнения каждой команды через STDIN.

2. Разработка AGI на Python 3 (без сторонних библиотек)

Создайте исполняемый скрипт /var/lib/asterisk/agi-bin/crm_lookup.py:

#!/usr/bin/env python3
import sys

def agi_read():
    env = {}
    while True:
        line = sys.stdin.readline().strip()
        if not line:
            break
        key, _, val = line.partition(':')
        env[key.strip()] = val.strip()
    return env

def agi_command(cmd):
    sys.stdout.write(f"{cmd}\n")
    sys.stdout.flush()
    return sys.stdin.readline().strip()

def main():
    env = agi_read()
    caller_id = env.get('agi_callerid', 'unknown')
    
    # Имитация запроса в CRM
    vip_client = True if caller_id == "79991234567" else False
    
    if vip_client:
        agi_command('SET VARIABLE CRM_ROUTE "VIP"')
        agi_command('VERBOSE "Client is VIP! Routing to Senior Queue" 1')
    else:
        agi_command('SET VARIABLE CRM_ROUTE "DEFAULT"')

if __name__ == '__main__':
    main()
chmod +x /var/lib/asterisk/agi-bin/crm_lookup.py
chown asterisk:asterisk /var/lib/asterisk/agi-bin/crm_lookup.py

3. Вызов AGI из диалплана extensions.conf

[from-trunk]
exten => _X.,1,NoOp(Inbound call with AGI CRM Check)
 same => n,Answer()
 same => n,AGI(crm_lookup.py)
 same => n,GotoIf($["${CRM_ROUTE}" = "VIP"]?vip_queue:standard_queue)
 same => n(vip_queue),Queue(vip_support_queue)
 same => n,Hangup()
 same => n(standard_queue),Queue(general_support_queue)
 same => n,Hangup()

4. Включение отладки в консоли Asterisk CLI

asterisk -rx "agi set debug on"
💡 Практика специалистов: Всегда устанавливайте жесткий таймаут (Timeout 2-3 сек) на любые внешние HTTP-запросы к REST API CRM-систем внутри AGI. Зависший HTTP-запрос заблокирует телефонную линию звонящего абонента.

Частые вопросы (FAQ)

Почему обязателен sys.stdout.flush() / fflush(STDOUT) в AGI?

Стандартный вывод языков программирования буферизуется. Без принудительного сброса буфера (flush) Asterisk не получит отправленную команду вовремя, и процесс зависнет в ожидании ответа.

Что такое FastAGI и когда его следует использовать?

Обычный AGI форкает новый процесс ОС (fork/exec) на каждый звонок, что создает высокую нагрузку при 50+ вызовах/сек. FastAGI (agi://host:4573/script) работает как постоянно запущенный сетевой демон через TCP-сокеты без оверхеда на создание процессов.

Как передать аргументы в AGI скрипт из диалплана?

Передавайте аргументы через запятую: same => n,AGI(script.py,arg1,arg2). В скрипте они будут доступны в стандартном массиве sys.argv (Python) или $argv (PHP).

Что делать, если AGI скрипт прерывается при преждевременном сбросе трубки звонящим?

При сбросе вызова Asterisk отправляет сигнал SIGHUP скрипту. В скрипте необходимо установить перехватчик сигналов (Signal Handler), чтобы корректно закрыть подключения к БД и освободить дескрипторы.

Полезные материалы
Рекомендуем