I thought I would post a modified version of a php script that I have been using since the days of the PIAF forum.
I have now updated it to check both sip and pjsip trunks and send an email if it detects a trunk that is not registered.
It has been tested on FreePBX 15 Asterisk 16 though the original code goes back to 2009.
indent preformatted text by 4 spaces
#!/usr/bin/php
<?php
/*
Checks registrations of both sip and pjsip trunks and sends an email if failure detected.
Originally Based on monitor_trunk.php from <https://github.com/reconwireless/freepbx-trunk-monitor>
Originally published by Nikol S ns at eyo.com.au 2009/11/02 04:31:29
Modified 13 May 2018 by Les Desser
16 Mar 2021 by Les Desser - added new code for pjsip and completely restructured.
Tested on FreePBX 15 Asterisk 16
To setup,
1. Change constants as appropriate
2. Put this file somewhere (eg. var/lib/asterisk/agi-bin/trunk_check_registered.php)
3. chmod it to 750(#chmod 750 monitor_trunk.php). Either owned by root or asterisk(#chown root.root monitor_trunk.php).
4. Edit crontab file in /var/spool/cron/ for appropriate user (root or asterisk), and add something like:
x/5 * * * * var/lib/asterisk/agi-bin/trunk_check_registered.php
to the file. Last line in the cron file must have a carriage return!
Above entry in the cron file will run the script every n minutes - change x to *
WARNING: This code is sensitive to possible layout changes to the output of the asterisk 'show' commands.
If the column position for the registration status changes then the calls to function analyse_status
need to be changed appropriately.
*/
# =========================================================
# Change these as necessary
const K_EMAIL_ADDRESS = '[email protected]';
const K_SLEEP =20; # Short pause
const K_LOG_FILE = '/tmp/debug.log';
const K_ERROR_PREFIX = 'FreePBX Error: Trunk not Registered: ';
# =========================================================
# Problem registration texts are:
const K_ARRAY_ERROR_TEXT = array(
'Request Sent',
'No Authentication',
'Unregistered',
'Failed',
'Auth. Sent',
'Rejected',
'Timeout',
'Unknown'
);
# OK text
const K_REGISTERED = "Registered";
# Common Message text
const K_MSG_FAIL = " trunk failure. Current status:\r\n\r\n";
# 'show' command
const K_SHOW_SIP = '/usr/sbin/asterisk -rx "sip show registry"';
const K_SHOW_PJSIP = '/usr/sbin/asterisk -rx "pjsip show registrations"';
# =========================================================
# Check both sip and pjsip
check_all();
# =========================================================
function check_all() {
# Checks both sip and pjsip
# Each check returns both $show_reg_output and $state
# $show_reg_output is the output from the 'show' commands
# $state is either 'ok' or the failing line from $show_reg_output
# Check sip. Call returns ok or error text
$state = check_sip($show_reg_output);
# If failed then send an email and continue checking pjsip
if ($state != 'ok') {send_alert_email(K_EMAIL_ADDRESS, $state, 'SIP'.K_MSG_FAIL.$show_reg_output);}
# Check pjsip.
$state = check_pjsip($show_reg_output);
if ($state != 'ok') {send_alert_email(K_EMAIL_ADDRESS, $state, 'PJSIP'.K_MSG_FAIL.$show_reg_output);}
}
# =========================================================
function check_sip(&$show_reg_output) {
# Check status of sip trunks
# Pass back $show_reg_output as needed in email
# Return 'ok' or state of failed trunk
# Column 4 (5th) contains the Status value for 'sip show..'
$state = analyse_show_reg_output($show_reg_output, K_SHOW_SIP, 4);
# If all OK then return
if ($state == 'ok') return $state;
# Wait for K_SLEEP seconds and try again.
sleep(K_SLEEP);
$state = analyse_show_reg_output($show_reg_output, K_SHOW_SIP, 4);
# If cleared up then return
if ($state == 'ok') return $state;
# Still a problem. Try a 'reload', wait K_SLEEP seconds and check again
$ret = shell_exec('/usr/sbin/asterisk -rx "module reload chan_sip"');
sleep(K_SLEEP);
$state = analyse_show_reg_output($show_reg_output, K_SHOW_SIP, 4);
# All done.
return $state;
}
# =========================================================
function check_pjsip(&$show_reg_output) {
# Check status of pjsip trunks
# Pass back $show_reg_output as needed in email
# Return 'ok' or state of failed trunk
$show_reg_output = shell_exec('/usr/sbin/asterisk -rx "pjsip show registrations"');
# Column 3 (4th) contains the Status value for 'pjsip show..'
return analyse_show_reg_output($show_reg_output, K_SHOW_PJSIP, 3);
}
# =========================================================
# Analyse the output from the 'show reg' comand
function analyse_show_reg_output(&$show_reg_output, $show_command, $column_id) {
# $show_reg_output: multi-line output from the 'show' command
# $show_command: 'show' command to be executed
# $column_id: Column number (starting from 0) within $show_reg_output in which the actual Status value appears
# Get registration status report
$show_reg_output = shell_exec($show_command);
# Treat nothing returned as an error as even if no trunks exist, the command should return: No objects found.
if (strlen(trim($show_reg_output)) == 0) return "Registration status output is empty";
# Separate out each line of the report
$lines = explode("\n", str_replace("\r\n", "\n", trim($show_reg_output)));
# Go through each line looking for a problem
for ($i = 1; $i < count($lines) - 1; $i++) {
# Check for OK text - skip line if found
if (strpos($lines[$i], K_REGISTERED) !== false) continue;
# Check for specific error texts - return as bad when 1st error status text is found
foreach (K_ARRAY_ERROR_TEXT as $txt) {if (strpos($lines[$i], $txt) !== false) return $txt;}
# No matching registered or failed text found
# Maybe there is an other status we do not know about - treat as an error
# Break line into parts
$parts = preg_split('/\s+/', $lines[$i]);
# If there is no $column_id'th column then the line can be ignored.
if (!isset($parts[$column_id])) continue;
# If the text is not empty, then we assume it is some other error status.
if ($parts[$column_id] <> '') return "Unknown Registration status: " . $lines[$i];
}
# All trunks are OK
return 'ok';
}
# =========================================================
function send_alert_email($email_address, $subject, $email_content = '') {
mail($email_address, K_ERROR_PREFIX.$subject, $email_content);
}
# =========================================================
function writelog($log) {
$x=file_put_contents(K_LOG_FILE, date('Y-m-d H:i:s')." UT: ".$log."\n", FILE_APPEND);
}
# =========================================================
# Debug tool: route var_dump output to debug log
# Example of use: vardumptolog('xx $_REQUEST=',$_REQUEST);
function vardumptolog($txt,$var) {
# Turn on output-buffering
ob_start();
# Dump to buffer
var_dump($var);
# Get dumped string
$result = ob_get_contents();
ob_end_clean();
writelog($txt."=".$result);
}
?>