Asterisk function 'SHELL'

Обзор

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

Описание

Получаем вывод после выполнения указанной команды (в отличии от Asterisk app: System, которая вернет только true/false
Например: Set(foo=${SHELL(echo bar)})
Команда, вызываемая этой функцией, будет выполняться системной оболочкой, обычно указанной в переменной среды SHELL.
Существует множество различных системных оболочек, с разными поведением, поэтому результат, генерируемый этой функцией, может различаться между платформами. Если 'live_dangerously' в //'asterisk.conf'// установлен в 'no', эта функция может быть выполнена только из диалплана, а не из API.

синтаксис

SHELL(command)

Аргументы

command - Выполняемая команда.

Пример #1

[in]
exten => _1XX,1,Set(_OP1=${EXTEN})
exten => _1XX,n,set(_TST=${CALLERID(num)} 1 ${EXTEN})
exten => _1XX,n,Goto(s,1)

exten => s,1,Set(name=${SHELL(php /var/www/html/shmitrix/callerid.php ${TST})})
exten => s,n,Set(CALLERID(name)=${name})
exten => s,n,Set(CALLFILENAME=/mnt/share/${STRFTIME(${EPOCH},,%Y%m%d-%H%M%S)}-${CALLERID(num)}.wav)
exten => s,n,MixMonitor(${CALLFILENAME})
exten => s,n,Goto(from-internal,${OP1},1)

Пример #2 AntiDDOS

[from-test]
exten => s,1,NoOp(Incoming: caller number: ${CALLERID(num)})
exten => s,n,Set(resp=${SHELL(php /var/lib/asterisk/agi-bin/antiddos.php ${CALLERID(num)})});
exten => s,n,Gosubif($[${resp}==stop]?${EXTEN},${MATH(${PRIORITY}+1),int}:${EXTEN},${MATH(${PRIORITY}+2),int});
exten => s,n,Hangup()
exten => s,n,Set(CHANNEL(musicclass)=Amstrong)
exten => s,n,Goto(from-internal,1000,1)

antiddos.php

antiddos.php

<?php
$rules = array( 
                60 => 2, // Не более 2 звонков в минуту ( 60 секунд )
                3600 => 10 // Не более 10 звонков в час ( 3600 секунд )
);

if (!$argv[1] ) die("please use: '" . $argv[0] . " phone_number' \nfor example: ".$argv[0]." 88121234567\n");

// Открываем или создаем БД
$db = new SQLite3('/tmp/sqlite.db');
$db->exec('CREATE TABLE IF NOT EXISTS logs (phone bigint(12), datetime int(12))');

// Добавляем номер и дату звонка в базу
$phone = preg_replace('/[^0-9]/','', $argv[1]);
$db->exec("INSERT INTO logs (phone, datetime) VALUES ( '".$phone."','".time()."' )");

foreach( $rules as $secs => $limit ) {
    $res = $db->query( "SELECT count(*) as `c` FROM logs WHERE `phone` = '".$phone."' AND `datetime` >= " .( time() - $secs ) );
    $row = $res->fetchArray();
    // Если привышен лимит
    if ( $row['c'] > $limit ) {
        die('stop');   // возвращаем stop и выходим из скрипта
    }
}
// Очистка мусора - удаляем старые данные, чтобы не раздувать базу
$max_period = max(array_keys($rules) );
$db->exec("DELETE FROM logs WHERE `datetime` < " .( time() - $max_period ));
// возвращаем continue
die('continue');
?>

Пример #3

Intraservice API + Asterisk + cURL

Получим информацию при помощи curl запроса и используем ее в диалплане.
Запросы будем делать к API системы учета заявок IntraService

бизнес логика:

Абонент вводит номер заявки, Asterisk получает номер исполнителя по номеру заявки и соединяет с ним клиента.

Рис1. Настройки пользователя в интерфейсе IntraService

Легенда:
  • Получим значение поля «Мобильный телефон», в примере: «88001234567»
  • Запрос: curl -H "Authorization: Basic <BASE64>=" https://<YOURNAME>.intraservice.ru/api/task/"${task}"?include=User | json_pp | grep -e "\"MobilePhone\" : \".*\","
    • Пояснения по телу запроса:
  • получим что-то такое: "MobilePhone" : "88001234567",
  • ${phone} - переменная с полученным номером
    • в примере отправлена напрямую в транк, или же, например: goto(from-internal,${phone},1)
exten => _X.,1,noop(test)
   same => n,read(task,beep,,,4,15) ; получаем от абонента номер заявки
   same => n,set(output=${SHELL(curl -H "Authorization: Basic <BASE64>=" https://<YOURNAME>.intraservice.ru/api/task/"${task}"?include=User | json_pp| grep  -e  "\"MobilePhone\" : \".*\",")} ) ; отправляем зарос
   same => n,set(phone=${POP(output,: )}) ; препарируем данные, удаляем ключ и освобождаем от кавычек.
   same => n,set(phone=${SHIFT(phone)})
   same => n,set(foo1=${POP(phone,",)})
   same => n,set(foo2=${SHIFT(phone,",)})
   same => n,dial(SIP/${phone}@sip_trunk,,r) ;используем полученные данные для вызова

Парсинг JSON из командной строки

Утилита jq позволит разобрать JSON при запросе и упростит диалплан.

curl -H "Authorization: Basic <BASE64>" https://TEST.intraservice.ru/api/task/149?include=User | jq '.'  

полный ответ

полный ответ

{
  "Priorities": null,
  "Rights": null,
  "TaskTypeSettings": null,
  "Services": null,
  "Statuses": null,
  "Task": {
    "AssetIds": null,
    "Assets": null,
    "Categories": null,
    "CategoryIds": null,
    "Changed": "2018-07-12T10:24:23.363",
    "Closed": null,
    "CompletionStatus": null,
    "CoordinatorIds": null,
    "Coordinators": null,
    "IsCoordinatedForCoordinators": null,
    "Created": "2018-07-10T10:23:39.537",
    "Creator": "Администратор",
    "CreatorADGuid": null,
    "CreatorComments": null,
    "CreatorCompanyId": 30,
    "CreatorCompanyName": "Центральный офис",
    "CreatorCompanyPath": "30|",
    "CreatorCurrentLanguage": null,
    "CreatorEmail": "",
    "CreatorIP": "10.70.1.31",
    "CreatorId": 43,
    "CreatorIsArchive": false,
    "CreatorLogin": "admin",
    "CreatorMobilePhone": null,
    "CreatorPhone": null,
    "CreatorPosition": null,
    "CreatorRoleId": 37,
    "CreatorTimeZone": null,
    "Deadline": "2018-07-12T10:22:00",
    "Description": null,
    "EditorId": null,
    "Escalated": null,
    "Evaluation": null,
    "EvaluationId": null,
    "ExecutorGroup": null,
    "ExecutorGroupId": null,
    "ExecutorIds": "44",
    "Executors": "test1",
    "FieryFields": "Priority",
    "Files": null,
    "FileNames": null,
    "FileIds": null,
    "Hours": 0,
    "Id": 149,
    "IsClient": false,
    "IsMassIncident": false,
    "Name": "Тест1",
    "ObserverIds": null,
    "Observers": null,
    "ParentId": null,
    "Price": null,
    "PriorityDescription": "",
    "PriorityId": 9,
    "PriorityImage16Url": "https://TEST.intraservice.ru/img/priorities/priority3.gif",
    "PriorityName": "Средний",
    "ReactionDate": "2018-07-10T14:23:00",
    "ReactionOverdue": true,
    "ResolutionOverdue": true,
    "ServiceCode": "с1",
    "ServiceDescription": "сс",
    "ServiceId": 15,
    "ServiceIsArchive": false,
    "ServiceIsPublic": false,
    "ServiceName": "Сервис1",
    "ServiceParentId": null,
    "ServicePath": "15|",
    "ServiceStage": null,
    "ServiceStageId": null,
    "StatusDescription": "",
    "StatusId": 31,
    "StatusImage16Url": "https://TEST.intraservice.ru/img/statuses/actual16.png",
    "StatusImage24Url": "https://TEST.intraservice.ru/img/statuses/actual24.png",
    "StatusIsCommentRequired": false,
    "StatusIsFixed": false,
    "StatusIsFinal": false,
    "StatusName": "Открыта",
    "TaskRepeatRuleId": null,
    "Type": "Стандартный",
    "TypeId": 1004,
    "WorkflowId": 1,
    "IsConcurrence": false,
    "IsCoordinatedByCurrentUser": false
  },
  "TaskType": null,
  "Users": [
    {
      "ADGuid": null,
      "Comments": null,
      "CompanyId": 30,
      "CompanyName": "Центральный офис",
      "CompanyPath": null,
      "CurrentLanguage": null,
      "Email": "",
      "Id": 43,
      "IsArchive": false,
      "Login": "admin",
      "MobilePhone": null,
      "Name": "Администратор",
      "Phone": null,
      "Position": null,
      "RoleId": 37,
      "TimeZone": null,
      "Changed": null,
      "UtcOffset": ""
    },
    {
      "ADGuid": null,
      "Comments": null,
      "CompanyId": 30,
      "CompanyName": "Центральный офис",
      "CompanyPath": null,
      "CurrentLanguage": null,
      "Email": "email@maul.com",
      "Id": 44,
      "IsArchive": false,
      "Login": "emai@maul.com",
      "MobilePhone": "88001234567",
      "Name": "test1",
      "Phone": "5828",
      "Position": null,
      "RoleId": 55,
      "TimeZone": null,
      "Changed": null,
      "UtcOffset": ""
    }
  ]
}

А теперь только нужные данные - '.Users[1].MobilePhone':

curl -H "Authorization: Basic <BASE64>" https://TEST.intraservice.ru/api/task/149?include=User | jq -r '.Users[1].MobilePhone' | tr -d '\n' 

88001234567
Диалплан

На этот раз запросим значение поля «Phone»:

exten => _X.,1,noop(test)
   same => n,read(task,beep,,,4,15)
   same => n,set(phone=${SHELL(curl -H "Authorization: Basic <BASE64>" https://TEST.intraservice.ru/api/task/"${task}"?include=User | jq -r '.Users[1].Phone' | tr -d '\n')} )
   same => n,goto(from-internal,${phone},1)

Рис2. Вывод консоли Asterisk


Asterisk: функции диалплана

  • asterisk/func/shell.txt
  • Последние изменения: 2018/07/24