좋아요,이 시나리오입니다 : "큰 이미지"페이지를 실제로 보지 않고 이미지 미리보기 이미지를 다운로드 한 횟수를 찾으려면 로그를 구문 분석해야합니다 ... 이것은 기본적으로 핫 링크입니다 "엄지"와 "전체"이미지보기의 비율에 기반한 보호 시스템PHP에서 아파치 로그를 효율적으로 파싱하기
서버가 엄지 손톱에 대한 요청에 의해 끊임없이 포격됨을 고려할 때, 가장 효율적인 해결책은 디스크에 매일 기록하는 버퍼링 된 아파치 로그를 사용하는 것처럼 보입니다 , 1Mb를 실행 한 다음 주기적으로 로그를 분석하십시오.
제 질문은 다음과 같습니다. PHP에서 아파치 로그를 구문 분석하여 데이터를 저장하는 방법은 다음과 같습니다.
- 로그 사용 및 업데이트를 실시간으로, 그리고이 작업을 수행하는 동안 나는 그것을 읽을 수 있도록 내 PHP 스크립트를 필요로합니다 PHP 스크립트는 "기억"해야합니다
- 되는 부분 최소한이어야한다
- 메모리 소비를 두 번 같은 부분을 읽고 스큐 데이터하지 않도록 로그를 쉽게 몇 시간에 데이터의 10 기가비트에 도달 할 수 있기 때문에 그것은, 읽기, 로그인
는 PHP 로거 스크립트 60 초마다 한 번 호출되고 그 시간 동안 로그 라인을 처리 할 수 있습니다.
내가 함께 몇 가지 코드를 해킹 시도했다하지만 난 데 문제 파일 크기
다음을 "이동"로 포인터를 추적 할 수있는 방법을, 메모리의 최소 금액을 사용 찾는데 어려움이 로그의 일부입니다 :
212.180.168.244 - - [18/Jan/2012:20:06:57 +0100] "GET /t/0/11/11441/11441268.jpg HTTP/1.1" 200 3072 "-" "Opera/9.80 (Windows NT 6.1; U; pl) Presto/2.10.229 Version/11.60" "-"
122.53.168.123 - - [18/Jan/2012:20:06:57 +0100] "GET /t/0/11/11441/11441276.jpg HTTP/1.1" 200 3007 "-" "Opera/9.80 (Windows NT 6.1; U; pl) Presto/2.10.229 Version/11.60" "-"
143.22.203.211 - - [18/Jan/2012:20:06:57 +0100] "GET /t/0/11/11441/11441282.jpg HTTP/1.1" 200 4670 "-" "Opera/9.80 (Windows NT 6.1; U; pl) Presto/2.10.229 Version/11.60" "-"
여기에 귀하의 검토를 위해 코드를 첨부 :
<?php
//limit for running it every minute
error_reporting(E_ALL);
ini_set('display_errors',1);
set_time_limit(0);
include(dirname(__FILE__).'/../kframework/kcore.class.php');
$aj = new kajaxpage;
$aj->use_db=1;
$aj->init();
$db=kdbhandler::getInstance();
$d=kdebug::getInstance();
$d->debug=TRUE;
$d->verbose=TRUE;
$log_file = "/var/log/nginx/access.log"; //full path to log file when run by cron
$pid_file = dirname(__FILE__)."/../kframework/cron/cron_log.pid";
//$images_id = array("8308086", "7485151", "6666231", "8343336");
if (file_exists($pid_file)) {
$pid = file_get_contents($pid_file);
$temp = explode(" ", $pid);
$pid_timestamp = $temp[0];
$now_timestamp = strtotime("now");
//if (($now_timestamp - $pid_timestamp) < 90) return;
$pointer = $temp[1];
if ($pointer > filesize($log_file)) $pointer = 0;
}
else $pointer = 0;
$pattern = "/([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})[^\[]*\[([^\]]*)\][^\"]*\"([^\"]*)\"\s([0-9]*)\s([0-9]*)(.*)/";
$last_time = 0;
$lines_processed=0;
if ($fp = fopen($log_file, "r+")) {
fseek($fp, $pointer);
while (!feof($fp)) {
//if ($lines_processed>100) exit;
$lines_processed++;
$log_line = trim(fgets($fp));
if (!empty($log_line)) {
preg_match_all($pattern, $log_line, $matches);
//print_r($matches);
$size = $matches[5][0];
$matches[3][0] = str_replace("GET ", "", $matches[3][0]);
$matches[3][0] = str_replace("HTTP/1.1", "", $matches[3][0]);
$matches[3][0] = str_replace(".jpg/", ".jpg", $matches[3][0]);
if (substr($matches[3][0],0,3) == "/t/") {
$get = explode("-",end(explode("/",$matches[3][0])));
$imgid = $get[0];
$type='thumb';
}
elseif (substr($matches[3][0], 0, 5) == "/img/") {
$get1 = explode("/", $matches[3][0]);
$get2 = explode("-", $get1[2]);
$imgid = $get2[0];
$type='raw';
}
echo $matches[3][0];
// put here your sql insert or update
$imgid=(int) $imgid;
if (isset($type) && $imgid!=1) {
switch ($type) {
case 'thumb':
//use the second slave in the registry
$sql=$db->slave_query("INSERT INTO hotlink SET thumbviews=1, imageid=".$imgid." ON DUPLICATE KEY UPDATE thumbviews=thumbviews+1 ",2);
echo "INSERT INTO hotlink SET thumbviews=1, imageid=".$imgid." ON DUPLICATE KEY UPDATE thumbviews=thumbviews+1";
break;
case 'raw':
//use the second slave in the registry
$sql=$db->slave_query("INSERT INTO hotlink SET rawviews=1, imageid=".$imgid." ON DUPLICATE KEY UPDATE rawviews=rawviews+1",2);
echo "INSERT INTO hotlink SET rawviews=1, imageid=".$imgid." ON DUPLICATE KEY UPDATE rawviews=rawviews+1";
break;
}
}
// $imgid - image ID
// $size - image size
$timestamp = strtotime("now");
if (($timestamp - $last_time) > 30) {
file_put_contents($pid_file, $timestamp . " " . ftell($fp));
$last_time = $timestamp;
}
}
}
file_put_contents($pid_file, (strtotime("now") - 95) . " " . ftell($fp));
fclose($fp);
}
?>
그는 몇 시간 만에 10G의 데이터를 보았습니다. 필자가 실제로 필요로하는 것을 요약하기 전에 MySQL에서 바라는 것은 아닙니다. 이와 같은 데이터에 대한 전체 텍스트 인덱스 (MyISAM을 암시 함)는 재앙입니다. – Evert
@Evert : 그러나 iit는 0 바이트 로그 파일로 시작합니까? 내 대답을 보라. – Bytemain
빈 로그로 시작하지 않습니다 ... 그것은 수십 GB의 데이터로 시작됩니다 :/내가 스크립트가 메모리 할당 오류로 시간 초과를 게시 했으므로 어딘가에 누출이 있어야한다고 생각합니다. T는 그것을 찾은 것 같아요 ... 나는 fgets를 사용하여 메모리의 현재 줄을 유지하는 인상을 받고있었습니다. 포인터를 추적하는 "pid"파일 아이디어가 있습니까 ?? – Igor