При использовании inotify_read, pnctl_signal не прерывает inotify_read

Я строю программу синтаксического анализа журнала на PHP. Анализатор журнала считывает данные из файла журнала, созданного ProFTPD, а затем выполняет некоторые действия, если обнаруживает конкретные команды. Чтобы иметь возможность обнаруживать изменения в файле журнала, я использую Inotify. Если файл журнала становится слишком большим, я хочу повернуть журнал, отправив сигнал анализатору журнала, чтобы завершить обработку текущего файла и затем завершить анализатор журнала. Затем Logrotate перезапустит анализатор журналов после того, как убедится, что исходный файл, который читается, очищен.

Проблема в том, что когда я использую Inotify и когда inotify находится в состоянии блокировки, прерывания не будут работать.

Например:

#!/usr/bin/php -q
<?php
declare(ticks = 1);

$log_parser = new LogParser();
$log_parser->process_log();

class LogParser {

private $ftp_log_file = '/var/log/proftpd/proftpd.log';
# file descriptor for the log file
private $fd;
# inotify instance
private $inotify_inst;
# watch id for the inotifier
private $watch_id;

public function process_log() {
// Open an inotify instance
$this->inotify_inst = inotify_init();
$this->watch_id = inotify_add_watch($this->inotify_inst, $this->ftp_log_file, IN_MODIFY);

$this->fd = fopen($this->ftp_log_file, 'r');
if ($this->fd === false)
die("unable to open $this->ftp_log_file!\n");

pcntl_signal(SIGUSR1,  function($signal) {
$this->sig_handler($signal);
});

while (1) {
# If the thread gets blocked here, the signals do not work
$events = inotify_read($this->inotify_inst);
while ($line = trim(fgets($this->fd))) {
// Parse the log ...
}
}
fclose($this->fd);
// stop watching our directory
inotify_rm_watch($this->inotify_inst, $this->watch_id);
// close our inotify instance
fclose($this->inotify_inst);
}

private function sig_handler($signo) {
switch ($signo) {
case SIGUSR1:
// Do some action ...
}
}

}

Я знаю, что одним из решений может быть то, что я запускаю родительский процесс, а затем добавляю обработчик сигналов в этот родительский процесс. Родительский процесс должен запустить анализатор журнала, и анализатор журнала будет заблокирован inotify_read, но родительский процесс этого не сделает, но ему было интересно, есть ли решение, не включающее родительский процесс — может ли inotify поддерживать прерывания?

Спасибо

0

Решение

Нашел решение здесь: блокировка php inotify, но с таймаутом

Финальный код:

#!/usr/bin/php -q
<?php
declare(ticks = 1);

$log_parser = new LogParser();
$log_parser->process_log();

class LogParser {

private $ftp_log_file = '/var/log/proftpd/proftpd.log';
# file descriptor for the log file
private $fd;
# inotify instance
private $inotify_inst;
# watch id for the inotifier
private $watch_id;

public function process_log() {
// Open an inotify instance
$this->inotify_inst = inotify_init();
stream_set_blocking($this->inotify_inst, false);
$this->watch_id = inotify_add_watch($this->inotify_inst, $this->ftp_log_file, IN_MODIFY);

$this->fd = fopen($this->ftp_log_file, 'r');
if ($this->fd === false)
die("unable to open $this->ftp_log_file!\n");

pcntl_signal(SIGUSR1,  function($signal) {
$this->sig_handler($signal);
});

while (1) {
while (1) {
$r = array($this->inotify_inst);
$timeout = 60;
$w = array();
$e = array();
$time_left = stream_select($r, $w, $e, $timeout);
if ($time_left != 0) {
$events = inotify_read($this->inotify_inst);
if ($events) {
break;
}
}
}
while ($line = trim(fgets($this->fd))) {
// Parse the log ...
}
}
fclose($this->fd);
// stop watching our directory
inotify_rm_watch($this->inotify_inst, $this->watch_id);
// close our inotify instance
fclose($this->inotify_inst);
}

private function sig_handler($signo) {
switch ($signo) {
case SIGUSR1:
// Do some action ...
}
}

}

Предлагаемое решение не блокирует прерывания, а также переводит поток в неблокирующее состояние.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]