@Kennius
Начинающий фронт-эндер

Как получить строки при совпадении?

Есть файл(error log)
с содержимым надо выбрать только строки вида

2021/12/01 07:50:04 [error] 10085#10085: *45452 Nemesida WAF: the request 8ace8f47968cc947cb5458f9a76dbb4b blocked by rule ID 50002 in zone URL, client: 193.142.146.138, server: site.ru, request: "GET /wp-login.php HTTP/1.1", host: "site.ru"
2021/12/01 09:53:52 [error] 10286#10286: *51462 Nemesida WAF: the request f4e6ce5467bfeb29ad8f13125d46e205 blocked by rule ID 1914 in zone URL, client: 162.241.69.182, server: site.ru, request: "HEAD /adminer-4.5.1.php HTTP/1.1", host: "www.site.ru"
2021/12/01 09:56:57 [error] 10286#10286: *51600 Nemesida WAF: the request 6269aff912fc70c68e3d2ae261418ad5 blocked by rule ID 1914 in zone URL, client: 69.49.235.93, server: site.ru, request: "HEAD /adminer-4.5.2.php HTTP/1.1", host: "site.ru"


проверить есть ли в строке нужное слово не проблема, но как потом с ней работать?

$f = fopen('/var/www/site.ru/data/logs/site.ru.error.log','r');
while (!feof($f))
{
	$st_strpos = "Nemesida";
	$pos = strpos(fgets($f), $st_strpos);

        if ($pos !== false) {		
		//тут надо как раз получить ту строку
	}
}


Но strpos возвращает или положение или false, а мне надо из найденной строки ещё несколько параметров выдернуть
  • Вопрос задан
  • 156 просмотров
Решения вопроса 2
ipatiev
@ipatiev Куратор тега PHP
Потомок старинного рода Ипатьевых-Колотитьевых
Всё что вам нужно было - это сначала получить строку в переменную, а потом производить над ней любые действия

$f = fopen('/var/www/site.ru/data/logs/site.ru.error.log','r');
while (!feof($f))
{
  $line = fgets($f);
  $st_strpos = "Nemesida";
  $pos = strpos($line, $st_strpos);

        if ($pos !== false) {		
    // тут как раз строка унас уже ЕСТЬ! в переменной $line
  }
}
Ответ написан
Комментировать
irishmann
@irishmann
Научись пользоваться дебаггером
Что за переменная $line, откуда взял? По твоему коду ты работаешь с одной большой строкой. Не легче сразу читать файл в массив через file()? Элементами массива будут строки, перебираешь их и делаешь все что хочешь.
<?php 
    $file = file('/var/www/site.ru/data/logs/site.ru.error.log');
    foreach($file as $string){
        if(mb_stripos($string, 'Nemesida') !== false){
            echo 'Needle string : ', $string, '<br>';
            
            $re = '/(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})/';
            preg_match($re, $string, $ip);
            $client = $ip[1];
            echo 'client: ', $client, '<hr>';
            
        }
    }


UPD.: По замечанию Ипатьев о том что не стоит читать логи через file пошел гуглить способы. Наткнулся на это:
$fp = fopen('/path/to/log/file', 'r');
while (true) {
    $line = fgets($fp);
    if ($line === false) {
        echo "no new content, sleeping\n";
        sleep(3);
        fseek($fp, 0, SEEK_CUR);
    } else {
        echo $line;
    }
}

Думаю не возникнет вопросов как это адаптировать.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы