Назад | Перейти на главную страницу

Asterisk: отбрасывание звонков с ошибкой ast_yyerror

У меня периодически возникает проблема, когда звездочка воспроизводит наше приветствие вызывающему абоненту, а затем прерывает вызов, а не заставляет наши телефоны звонить.

Я не могу воспроизвести проблему ни с одним из имеющихся у меня телефонов, и многие абоненты прекрасно справляются с этим. Однако некоторые абоненты сталкиваются с проблемой, и я не могу найти для нее никакой закономерности.

В той информации, которую я смог найти, говорится, что это было вызвано ошибкой при вычислении выражения диалплана. Думаю, это такая строчка:

exten => START,n,GotoIf($[${FORCE_CLOSED}=TRUE]?CLOSED,1)

Но я не уверен, что с этим не так.

Я вижу на консоли следующую ошибку:

[Apr  4 16:29:49] WARNING[27038]: ast_expr2.fl:459 ast_yyerror: ast_yyerror():  syntax error: syntax error, unexpected '=', expecting $end; Input:=TRUE^

Выход окружающего пульта:

-- Executing [START@AGInbound:1] Answer("IAX2/AtlantaTeliax-10086", "") in new stack
-- Executing [START@AGInbound:2] BackGround("IAX2/AtlantaTeliax-10086", 0000_AG_THANK_YOU_FOR_CALLING_AG") in new stack
--  Playing '0000_AG_THANK_YOU_FOR_CALLING_AG.slin' (language 'en')
[Apr  4 16:29:49] WARNING[27038]: ast_expr2.fl:459 ast_yyerror: ast_yyerror():  syntax error: syntax error, unexpected '=', expecting $end; Input:
=TRUE
^
[Apr  4 16:29:49] WARNING[27038]: ast_expr2.fl:463 ast_yyerror: If you have questions, please refer to doc/tex/channelvariables.tex in the asterisk source.
    -- Executing [START@AGInbound:3] GotoIf("IAX2/AtlantaTeliax-10086", "?CLOSED,1") in new stack
    -- Executing [START@AGInbound:4] GotoIfTime("IAX2/AtlantaTeliax-10086", "9:30-17:0|mon-fri|*|*?OPEN,1") in new stack
    -- Executing [START@AGInbound:5] GotoIfTime("IAX2/AtlantaTeliax-10086", "10:0-18:30|sat|*|*?OPEN,1") in new stack
    -- Executing [START@AGInbound:6] GotoIfTime("IAX2/AtlantaTeliax-10086", "12:0-17:0|sun|*|*?OPEN,1") in new stack

Соответствующие строки из абонентской группы:

exten => START,1,Answer()
exten => START,n,Background(0000_AG_THANK_YOU_FOR_CALLING_AG)

; See if we're open
; Force Closed if no one's going to be answering
exten => START,n,GotoIf($[${FORCE_CLOSED}=TRUE]?CLOSED,1)

exten => START,n,GotoIfTime(${AG_WEEKDAY_OPEN_HOUR}:${AG_WEEKDAY_OPEN_MIN}-${AG$
exten => START,n,GotoIfTime(${AG_SATURDAY_OPEN_HOUR}:${AG_SATURDAY_OPEN_MIN}-${$
exten => START,n,GotoIfTime(${AG_SUNDAY_OPEN_HOUR}:${AG_SUNDAY_OPEN_MIN}-${AG_S$
; ...and we're not. But maybe the time of day has been overridden?
exten => START,n,GotoIf($[${OVERRIDE_TIME_OF_DAY}=TRUE]?OPEN,1)
; No override... We're definatly closed.
exten => START,n,Goto(CLOSED,1)

Есть идеи, что не так с выражением? Недавно мы обновились с 1.4 до 1.6.

В звездочке $[] выражение, неопределенные переменные не возвращают неявную пустую строку или ноль. Они раскрываются как «ничего» до оценки выражения, поэтому после расширения переменной (до нуля) она не видна синтаксическому анализатору выражения. Это вызывает ошибку, уже отмеченную Пабло Альсиной:

GotoIf("IAX2/AtlantaTeliax-10086", "?CLOSED,1")

Избежать этого можно двумя способами:

  1. Всегда задавайте своим переменным разумные значения по умолчанию, прежде чем использовать их (как предложил Пабло).
  2. В любом $[] выражение, заключите свои переменные и литералы в двойные кавычки. Это приведет к тому, что неопределенная переменная будет обрабатываться как пустая строка, которую все еще можно использовать для сравнения.

Лично я стараюсь делать и то, и другое. Например:

exten => START,n,Set(FORCE_CLOSED=FALSE)
exten => START,n,GotoIf($["${FORCE_CLOSED}"="TRUE"]?CLOSED,1)

Обратите внимание на двойные кавычки вокруг ${FORCE_CLOSED} и значение для сравнения. Даже если переменная не определена, выражение будет иметь "" (пустая строка) для сравнения с "TRUE".

На самом деле, вы можете использовать любой символ, который вам нравится, потому что он просто будет добавлен к расширению переменной. Он просто дает вам буквальное значение, которое гарантированно будет там, если переменная не определена. Мне нравятся цитаты, потому что они делают код похожим на другие языки программирования. Вы могли бы так же легко использовать что-то вроде $[x${FORCE_CLOSED}=xTRUE], который обычно встречается в сценариях оболочки Bourne. Конечный результат такой же.

Вот что я могу вам сказать.

yyerror - это ошибка парсера, созданного yacc.

Ошибка жалуется на =. Похоже, что в этой строке знак = - это конструкция, которую грамматика не поддерживает.

Удачи на serverfault.com, где находится этот вопрос ...

Кто определяет $ {FORCE_CLOSED}?

Из того, что я вижу, кажется, что эта переменная иногда не получает начальное значение, а затем синтаксический анализатор выдает ошибку, когда вы оцениваете

GotoIf("IAX2/AtlantaTeliax-10086", "?CLOSED,1")

Убедитесь, что вызовы, вызывающие ошибку, имеют разумное значение FORCE_CLOSED