编写 AGI 脚本与 Asterisk 交互时,一旦脚本出错,在控制台(asterisk -crvvvvvvvvvvvv)上又看不出错误,只能把 stdin 改为具体的变量,在直接调用脚本,但这样很不方便。趟过几次坑之后,把调试的步骤记录下来,以便后来者规避此坑。
首先,配置 php.ini 的 display_error 和 error_log
display_error = off
error_log = /var/log/mylogfile
其次,在脚本里记录日志,同时脚本必须具有执行权限
#!/usr/bin/php -q
<?php
function write_log($data)
{
global $config;
file_put_contents('/var/log/' . date('Ymd') . '.log', $data . PHP_EOL, FILE_APPEND);
}
$stdin = fopen('php://stdin', 'r');
$stdout = fopen('php://stdout', 'w');
while (!feof($stdin))
{
$temp = fgets($stdin);
if (strpos($temp, ':') === false)
break;
// Strip off any new-line characters
$temp = str_replace("\n", "", $temp);
write_log("stdin:" . $temp);
$s = explode(":", $temp);
$agivar[$s[0]] = trim($s[1]);
}
function execute_agi($command)
{
global $stdin, $stdout;
fputs($stdout, $command . "\n");
fflush($stdout);
$result = fgets($stdin, 4096);
write_log('agi result: ' . $result);
return $result;
}
$flag = 'debug demo';
execute_agi("SET VARIABLE FLAG \"$flag\"");
以下为日志信息
stdin:agi_request: judge.php
stdin:agi_channel: SIP/siptrunk-00000081
stdin:agi_language: en
stdin:agi_type: SIP
stdin:agi_uniqueid: 1531906486.129
stdin:agi_version: 11.25.1
stdin:agi_callerid: 11111111111
stdin:agi_calleridname: unknown
stdin:agi_callingpres: 0
stdin:agi_callingani2: 0
stdin:agi_callington: 0
stdin:agi_callingtns: 0
stdin:agi_dnid: 22222222
stdin:agi_rdnis: unknown
stdin:agi_context: incoming
stdin:agi_extension: 22222222
stdin:agi_priority: 1
stdin:agi_enhanced: 0.0
stdin:agi_accountcode:
stdin:agi_threadid: 140502522619648
stdin:agi_arg_1: 11111111111
stdin:agi_arg_2: SIP/siptrunk-00000081
agi result: 200 result=1
可以看到日志最后的那行记录 agi result: 200 result=1
,是 AGI 脚本与 Asterisk 交互返回的结果,这点很重要,关系着拨号计划能否按照指定规则走下去,具体返回状态如下
Code | Example result text |
---|---|
200 | result=1 |
510 | Invalid or unknown command |
511 | Command Not Permitted on a dead channel |
520 | End of proper usage |
注意,在 write_log 方法中,写入的字符串,因此如果要把数组转为字符串需用 var_export($array, 1),注意一定得加上 1 参数,把数组转为字符串,否则会是个数组的,在执行 execute_agi 方法里的 fflush 时会把整个数组的字符串形式及命令直接传给 Asterisk,这时返回值便是 510 Invalid or unknown command
。下面可以测试下
var_export([1,2,3,4,5]); echo 1; $stdout = fopen('php://stdout', 'w'); fflush($stdout);
执行打印的信息如下
array (
0 => 1,
1 => 2,
2 => 3,
3 => 4,
4 => 5,
)1