среда, 23 декабря 2015 г.

Автоматическое удаление старых записей разговоров в Elastix по расписанию. Правильный способ.

Этот способ полностью автоматизирует удаление старых записей разговоров и корректно вносит изменения базу данных так, что Elastix видит, что файл с записью был удалён.
Elastix хранит все записи разговоров в базе данных asteriskcdrdb в таблице cdr. В этой же таблице в поле userfield есть и ссылка на аудиозапись. Эту ссылку нам и нужно поменять на значение audio:deleted
Для решения этой задачи напишем небольшой php скрипт который удалит файлы по требуемому условию давности и удалит ссылки на них в таблице БД.

То же самое можно сделать и с помощью более простого bash-скрипта. Я же здесь привожу пример с php, поскольку данный скрипт является одной из составных частей моей собственной надстройки над Elastix, выполняющей сугубо специфические производственные задачи и не интересной в рамках данной темы.
Обычно я все самописные скрипты храню в корне в специльной папке /scripts. Там же и создадим php скрипт del_cdr.php такого вида (код обновлён 11.04.2016 в связи с обнаруженным NOTICE):
<?php

$asterisk_monitor_dir = '/var/spool/asterisk/monitor/'; //директория с записями разговоров
$days_to_delete = 365;                                  //сколько дней хранить записи
$db_host = 'localhost';                                 //адрес сервера БД - обычно localhost
$db_user = 'asteriskuser';                              //пользователь для подключения к БД
$db_pass = 'ваш_пароль_пользователя_asteriskuser';      //пароль для подключения к БД
$database = 'asteriskcdrdb';                            //БД asterisk для хранения CDR

// получаем список файлов с датой создания старше $days_to_delete дней
$p = popen("find ".$asterisk_monitor_dir." -type f -mtime +".$days_to_delete, "r") or die("!popen\n");
// подключаемся с БД с CDR
$conn = mysql_connect($db_host, $db_user, $db_pass) or die(mysql_error());
$db = mysql_select_db($database, $conn);

//удаляем файлы из полученного списка и ссылки на них из БД
while (!feof($p)) {
    $path = fgets($p);
    $file = str_replace($asterisk_monitor_dir,'',$path);
    preg_match('/\\d{1,}[.]\\d{1,}/', $file, $uniqueid);
    
    //если есть уникальный идентификатор звонка, то
    //удаляем запись этого звонка и обновляем информацию в БД
    if (isset($uniqueid[0])) {
        $uniqueid = $uniqueid[0];
        //удаляем файл
        exec('rm -f '.$path);
        //обновляем БД
        $sql = "update cdr set userfield='audio:deleted' where uniqueid='".$uniqueid."'";
        mysql_query($sql, $conn);
    }

}
pclose($p);
mysql_close($conn);

?>
Не забываем дать права на выполнение:
chmod +x del_cdr.php
Для ежедневного автоматического запуска скрипта воспользуемся crontab'ом
crontab -e
и добавим туда такую строку:
0 0 * * * php /scripts/del_cdr.php
Теперь наш скрипт будет ежедневно чистить диск от записей разговоров с истекшим сроком давности и при этом корректно сообщать Elastix, что файлы удалены. В итоге сделав выборку записей годичной давности в web-интерфейсе мы увидим следующее:
Ну и напоследок, дам один совет. Никогда не соглашайтесь на автоматическое разбиение диска при установке Elastix, а разбивайте его вручную. Помимо стандартных разделов для /boot, swap и / обязательно создавайте отдельный раздел для /var/spool/asterisk/monitor
Это позволит избежать полного падения всего в случае переполнения диска, так как основные процессы как ОС, так и Elastix не будут работать с переполненным разделом. В таком случае при переполнении /var/spool/asterisk/monitor самой большой неприятностью будут просто не записанные разговоры, при этом вся система продолжит работать в штатном режиме.

6 комментариев:

  1. Добрый день,
    спасибо за статью. При попытке запустить скрипт, выскакивает сообщение вида - PHP Notice: Undefined offset: 0 in /scripts/del_cdr.php on line 23
    т.е. это строка $uniqueid = $uniqueid[0];

    Это сообщение должно появляться или есть ошибка?

    ОтветитьУдалить
    Ответы
    1. Здравствуйте! Да, есть такой баг в коде. Спасибо, что обнаружили.
      Возникает он тогда, когда под выбранное условие не попадает ни одного файла. Соответственно мы пытаемся присвоить переменной $uniqueid значение элемента массива, которого не существует.
      Замените строку 23 на строку следующего вида:
      if (isset($uniqueid[0])) {$uniqueid = $uniqueid[0];}
      и предупреждение больше не будет высвечиваться. Чуть позже я доработаю код в посте.

      Удалить
  2. на elastix 4 ошибка при запуске:
    ./del_monitor.php
    ./del_monitor.php: line 1: ?php: No such file or directory
    ./del_monitor.php: line 3: =: command not found
    ./del_monitor.php: line 3: //директория: No such file or directory
    ./del_monitor.php: line 4: =: command not found
    ./del_monitor.php: line 4: //сколько: No such file or directory
    ./del_monitor.php: line 5: =: command not found
    ./del_monitor.php: line 5: //адрес: No such file or directory
    ./del_monitor.php: line 6: =: command not found
    ./del_monitor.php: line 6: //пользователь: No such file or directory
    ./del_monitor.php: line 7: =: command not found
    ./del_monitor.php: line 7: //пароль: No such file or directory
    ./del_monitor.php: line 8: =: command not found
    ./del_monitor.php: line 8: //БД: No such file or directory
    ./del_monitor.php: line 10: //: Is a directory
    ./del_monitor.php: line 11: syntax error near unexpected token `('
    ./del_monitor.php: line 11: `$p = popen("find ".$asterisk_monitor_dir." -type f -mtime +".$days_to_delete, "r") or die("!popen\n");'

    ОтветитьУдалить
  3. Ответы
    1. В самое начало файла первой строкой перед <?php добавьте
      #!/usr/bin/php

      Удалить
    2. спасибо!!! работает на elastix 4, elastix 2.3.0

      Удалить