本文目录导读:

我来为您创建一个功能完善的PHP访问日志分析脚本:
基础版本
<?php
/**
* PHP访问日志分析脚本
* 使用方法: php log_analyzer.php /path/to/access.log
*/
class LogAnalyzer {
private $logFile;
private $totalRequests = 0;
private $uniqueIPs = [];
private $statusCodes = [];
private $requestMethods = [];
private $urls = [];
private $userAgents = [];
private $trafficBytes = 0;
private $timeStats = [];
private $slowestRequests = [];
private $errorLogs = [];
public function __construct($logFile) {
if (!file_exists($logFile)) {
die("错误: 日志文件不存在\n");
}
$this->logFile = $logFile;
}
public function analyze() {
echo "开始分析日志文件: {$this->logFile}\n";
echo str_repeat("=", 60) . "\n\n";
$handle = fopen($this->logFile, 'r');
if (!$handle) {
die("错误: 无法打开日志文件\n");
}
$lineCount = 0;
$startTime = microtime(true);
while (($line = fgets($handle)) !== false) {
$lineCount++;
$this->parseLine($line);
// 显示进度
if ($lineCount % 10000 === 0) {
echo "已处理 {$lineCount} 行...\n";
}
}
fclose($handle);
$elapsed = microtime(true) - $startTime;
echo "\n分析完成! 耗时: " . round($elapsed, 2) . " 秒\n\n";
$this->printReport();
}
private function parseLine($line) {
// 解析Apache/Nginx日志格式
// 示例: 127.0.0.1 - - [10/Oct/2023:13:55:36 +0000] "GET /index.php HTTP/1.1" 200 2326 "http://example.com" "Mozilla/5.0"
$pattern = '/^(\S+) (\S+) (\S+) \[([^\]]+)\] "([^"]*)" (\d{3}) (\d+) "([^"]*)" "([^"]*)"$/';
if (preg_match($pattern, $line, $matches)) {
$ip = $matches[1];
$time = $matches[4];
$request = $matches[5];
$status = $matches[6];
$bytes = $matches[7];
$referer = $matches[8];
$userAgent = $matches[9];
// 统计各项数据
$this->totalRequests++;
$this->uniqueIPs[$ip] = ($this->uniqueIPs[$ip] ?? 0) + 1;
$this->statusCodes[$status] = ($this->statusCodes[$status] ?? 0) + 1;
// 解析请求方法
if (preg_match('/^(\S+) (\S+) (\S+)/', $request, $reqMatches)) {
$method = $reqMatches[1];
$url = $reqMatches[2];
$this->requestMethods[$method] = ($this->requestMethods[$method] ?? 0) + 1;
$this->urls[$url] = ($this->urls[$url] ?? 0) + 1;
}
$this->userAgents[$userAgent] = ($this->userAgents[$userAgent] ?? 0) + 1;
$this->trafficBytes += intval($bytes);
// 记录4xx和5xx错误
if ($status >= 400) {
$this->errorLogs[] = [
'ip' => $ip,
'time' => $time,
'request' => $request,
'status' => $status
];
}
// 记录最慢请求 (每分钟的请求数)
$timeKey = substr($time, 0, 2) . ':00';
$this->timeStats[$timeKey] = ($this->timeStats[$timeKey] ?? 0) + 1;
}
}
private function printReport() {
echo "=== 访问日志分析报告 ===\n\n";
// 1. 总体统计
echo "【总体统计】\n";
echo "总请求数: " . number_format($this->totalRequests) . "\n";
echo "独立IP数: " . count($this->uniqueIPs) . "\n";
echo "总流量: " . $this->formatBytes($this->trafficBytes) . "\n";
echo "平均每个请求流量: " . $this->formatBytes($this->trafficBytes / max(1, $this->totalRequests)) . "\n\n";
// 2. 状态码分布
echo "【HTTP状态码分布】\n";
arsort($this->statusCodes);
foreach ($this->statusCodes as $status => $count) {
$percent = ($count / $this->totalRequests) * 100;
echo " {$status}: " . number_format($count) . " (" . round($percent, 2) . "%)\n";
}
echo "\n";
// 3. 请求方法分布
echo "【请求方法分布】\n";
arsort($this->requestMethods);
foreach ($this->requestMethods as $method => $count) {
echo " {$method}: " . number_format($count) . "\n";
}
echo "\n";
// 4. Top 10 IP地址
echo "【Top 10 IP地址】\n";
arsort($this->uniqueIPs);
$topIPs = array_slice($this->uniqueIPs, 0, 10, true);
$rank = 1;
foreach ($topIPs as $ip => $count) {
echo " {$rank}. {$ip} - " . number_format($count) . " 次请求\n";
$rank++;
}
echo "\n";
// 5. Top 10 访问页面
echo "【Top 10 访问页面】\n";
arsort($this->urls);
$topURLs = array_slice($this->urls, 0, 10, true);
$rank = 1;
foreach ($topURLs as $url => $count) {
echo " {$rank}. {$url} - " . number_format($count) . " 次\n";
$rank++;
}
echo "\n";
// 6. 每小时请求分布
echo "【每小时请求分布】\n";
ksort($this->timeStats);
$maxCount = max($this->timeStats);
foreach ($this->timeStats as $hour => $count) {
$barLength = (int)($count / $maxCount * 50);
$bar = str_repeat('#', $barLength);
echo " {$hour}: " . number_format($count) . " {$bar}\n";
}
echo "\n";
// 7. 错误请求统计
$errorCount = count($this->errorLogs);
if ($errorCount > 0) {
echo "【错误请求统计】\n";
echo "4xx/5xx错误总数: " . number_format($errorCount) . "\n";
// 按IP统计错误
$errorsByIP = [];
foreach ($this->errorLogs as $error) {
$errorsByIP[$error['ip']] = ($errorsByIP[$error['ip']] ?? 0) + 1;
}
arsort($errorsByIP);
echo "\n错误最多的IP:\n";
$topErrors = array_slice($errorsByIP, 0, 5, true);
foreach ($topErrors as $ip => $count) {
echo " {$ip}: " . number_format($count) . " 次错误\n";
}
// 显示最近5条错误
echo "\n最近5条错误:\n";
$recentErrors = array_slice($this->errorLogs, -5);
foreach ($recentErrors as $error) {
echo " [{$error['time']}] {$error['ip']} - {$error['status']} - {$error['request']}\n";
}
}
// 8. Top 10 User Agents
echo "\n【Top 10 User Agents】\n";
arsort($this->userAgents);
$topAgents = array_slice($this->userAgents, 0, 10, true);
$rank = 1;
foreach ($topAgents as $agent => $count) {
$shortAgent = strlen($agent) > 50 ? substr($agent, 0, 47) . "..." : $agent;
echo " {$rank}. {$shortAgent} - " . number_format($count) . " 次\n";
$rank++;
}
}
private function formatBytes($bytes) {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$bytes = max(0, $bytes);
$power = $bytes > 0 ? floor(log($bytes, 1024)) : 0;
$power = min($power, count($units) - 1);
$value = $bytes / pow(1024, $power);
return number_format($value, 2) . ' ' . $units[$power];
}
}
// 命令行入口
if (php_sapi_name() === 'cli') {
if ($argc < 2) {
echo "使用方法: php " . basename($argv[0]) . " /path/to/access.log\n";
echo "示例: php " . basename($argv[0]) . " /var/log/apache2/access.log\n";
exit(1);
}
$logFile = $argv[1];
try {
$analyzer = new LogAnalyzer($logFile);
$analyzer->analyze();
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "\n";
exit(1);
}
}
进阶版本(带JSON输出和更多功能)
<?php
/**
* 增强版PHP访问日志分析脚本
* 支持多种输出格式和高级分析
*/
class AdvancedLogAnalyzer {
private $logFile;
private $data = [];
private $config;
public function __construct($logFile, $config = []) {
$this->logFile = $logFile;
$this->config = array_merge([
'output_format' => 'text', // text, json, csv
'top_count' => 10,
'user_agent_filter' => null,
'ip_filter' => null,
'time_filter_start' => null,
'time_filter_end' => null,
'status_code_filter' => null,
], $config);
$this->initializeData();
}
private function initializeData() {
$this->data = [
'total_requests' => 0,
'total_bytes' => 0,
'ips' => [],
'status_codes' => [],
'methods' => [],
'urls' => [],
'user_agents' => [],
'referrers' => [],
'time_series' => [],
'errors' => [],
'slow_requests' => [],
'performance' => [
'total_time' => 0,
'max_time' => 0,
'avg_time' => 0
]
];
}
public function analyze() {
if (!file_exists($this->logFile)) {
throw new Exception("日志文件不存在: {$this->logFile}");
}
$handle = fopen($this->logFile, 'r');
if (!$handle) {
throw new Exception("无法打开日志文件");
}
$lineCount = 0;
$startTime = microtime(true);
while (($line = fgets($handle)) !== false) {
$lineCount++;
$this->processLine($line);
// 进度显示
if ($lineCount % 50000 === 0) {
echo "\r已处理: " . number_format($lineCount) . " 行...";
}
}
fclose($handle);
$this->data['performance']['total_time'] = microtime(true) - $startTime;
$this->data['total_lines'] = $lineCount;
echo "\r处理完成: " . number_format($lineCount) . " 行\n";
return $this->generateReport();
}
private function processLine($line) {
// 支持常用日志格式
$patterns = [
// Nginx/Apache 组合格式
'/^(\S+) (\S+) (\S+) \[([^\]]+)\] "(\S+) (\S+) [^"]*" (\d{3}) (\d+) "([^"]*)" "([^"]*)"(?: "(.*)")?$/',
// 简化格式
'/^(\S+) \[([^\]]+)\] "(\S+) (\S+) [^"]*" (\d{3}) (\d+)$/'
];
foreach ($patterns as $pattern) {
if (preg_match($pattern, $line, $matches)) {
$this->parseMatch($matches);
break;
}
}
}
private function parseMatch($matches) {
$ip = $matches[1];
// 获取时间
preg_match('/\[([^\]]+)\]/', $matches[0], $timeMatch);
$timestamp = strtotime($timeMatch[1]);
// 应用过滤条件
if (!$this->applyFilters($ip, $timestamp)) {
return;
}
// 请求信息
if (count($matches) >= 10) {
$method = $matches[5];
$url = $matches[6];
$status = $matches[7];
$bytes = $matches[8];
$referer = $matches[9];
$userAgent = $matches[10];
} else {
$method = $matches[3];
$url = $matches[4];
$status = $matches[5];
$bytes = $matches[6];
$referer = '';
$userAgent = '';
}
// 更新统计数据
$this->data['total_requests']++;
$this->data['total_bytes'] += intval($bytes);
$this->incrementCounter('ips', $ip);
$this->incrementCounter('status_codes', $status);
$this->incrementCounter('methods', $method);
$this->incrementCounter('urls', $url);
$this->incrementCounter('user_agents', $userAgent);
$this->incrementCounter('referrers', $referer);
// 时间序列分析
$hourKey = date('Y-m-d H:00', $timestamp);
$this->incrementCounter('time_series', $hourKey);
// 错误日志
if ($status >= 400) {
$this->data['errors'][] = [
'ip' => $ip,
'time' => date('Y-m-d H:i:s', $timestamp),
'url' => $url,
'method' => $method,
'status' => $status,
'user_agent' => $userAgent
];
}
}
private function incrementCounter($category, $key) {
if (!isset($this->data[$category][$key])) {
$this->data[$category][$key] = 0;
}
$this->data[$category][$key]++;
}
private function applyFilters($ip, $timestamp) {
if ($this->config['ip_filter'] && $ip !== $this->config['ip_filter']) {
return false;
}
return true;
}
private function generateReport() {
$data = $this->data;
// 计算统计信息
$totalRequests = $data['total_requests'];
$uniqueIPs = count($data['ips']);
$successRate = $totalRequests > 0 ? ($data['status_codes'][200] ?? 0) / $totalRequests * 100 : 0;
$errorRate = $totalRequests > 0 ? 100 - $successRate : 0;
// Top N 排序
arsort($data['ips']);
arsort($data['urls']);
arsort($data['user_agents']);
arsort($data['status_codes']);
$report = [
'metadata' => [
'generated_at' => date('Y-m-d H:i:s'),
'log_file' => basename($this->logFile),
'analysis_time' => round($data['performance']['total_time'], 2) . 's'
],
'summary' => [
'total_requests' => $totalRequests,
'unique_ips' => $uniqueIPs,
'total_traffic' => $this->formatBytes($data['total_bytes']),
'avg_requests_per_ip' => round($totalRequests / max(1, $uniqueIPs), 2),
'success_rate' => round($successRate, 2) . '%',
'error_rate' => round($errorRate, 2) . '%'
],
'status_codes' => array_slice($data['status_codes'], 0, $this->config['top_count'], true),
'top_ips' => array_slice($data['ips'], 0, $this->config['top_count'], true),
'top_urls' => array_slice($data['urls'], 0, $this->config['top_count'], true),
'top_user_agents' => array_slice($data['user_agents'], 0, $this->config['top_count'], true),
'request_methods' => $data['methods'],
'hourly_stats' => $data['time_series'],
'errors' => array_slice($data['errors'], 0, $this->config['top_count'])
];
return $this->formatOutput($report);
}
private function formatOutput($report) {
switch ($this->config['output_format']) {
case 'json':
return json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
case 'csv':
return $this->toCSV($report);
default:
return $this->toText($report);
}
}
private function toText($report) {
$output = "=== 访问日志分析报告 ===\n";
$output .= "生成时间: {$report['metadata']['generated_at']}\n";
$output .= "日志文件: {$report['metadata']['log_file']}\n";
$output .= "分析耗时: {$report['metadata']['analysis_time']}\n\n";
//
$output .= "【总体概况】\n";
foreach ($report['summary'] as $key => $value) {
$output .= " " . ucwords(str_replace('_', ' ', $key)) . ": {$value}\n";
}
// 状态码
$output .= "\n【状态码分布】\n";
foreach ($report['status_codes'] as $code => $count) {
$output .= " {$code}: " . number_format($count) . "\n";
}
// Top IPs
$output .= "\n【Top IP地址】\n";
$rank = 1;
foreach ($report['top_ips'] as $ip => $count) {
$output .= " {$rank}. {$ip} - " . number_format($count) . " 次\n";
$rank++;
}
// Top URLs
$output .= "\n【热门URL】\n";
$rank = 1;
foreach ($report['top_urls'] as $url => $count) {
$shortUrl = strlen($url) > 60 ? substr($url, 0, 57) . "..." : $url;
$output .= " {$rank}. {$shortUrl} - " . number_format($count) . " 次\n";
$rank++;
}
return $output;
}
private function toCSV($report) {
// CSV输出逻辑
$output = fopen('php://temp', 'r+');
fputcsv($output, ['指标', '数值']);
foreach ($report['summary'] as $key => $value) {
fputcsv($output, [ucwords(str_replace('_', ' ', $key)), $value]);
}
rewind($output);
$csv = stream_get_contents($output);
fclose($output);
return $csv;
}
private function formatBytes($bytes) {
$units = ['B', 'KB', 'MB', 'GB', 'TB'];
$i = 0;
while ($bytes >= 1024 && $i < count($units) - 1) {
$bytes /= 1024;
$i++;
}
return round($bytes, 2) . ' ' . $units[$i];
}
// 保存报告到文件
public function saveReport($report, $filename = null) {
$filename = $filename ?? 'report_' . date('Ymd_His') . '.txt';
file_put_contents($filename, $report);
echo "报告已保存到: " . $filename . "\n";
}
}
// 命令行界面
if (php_sapi_name() === 'cli') {
// 解析命令行参数
$options = getopt('f:o:t:h', ['file:', 'output:', 'top:', 'help']);
echo "PHP访问日志分析工具 v2.0\n";
echo "==========================\n\n";
if (isset($options['h']) || $options['help']) {
echo "用法: php log_analyzer_v2.php -f <日志文件> [选项]\n\n";
echo "必选参数:\n";
echo " -f, --file <path> 指定日志文件路径\n\n";
echo "可选参数:\n";
echo " -o, --output <format> 输出格式: text|json|csv (默认: text)\n";
echo " -t, --top <number> 显示Top N条数据 (默认: 10)\n";
echo " -h, --help 显示帮助信息\n";
echo "\n示例:\n";
echo " php log_analyzer_v2.php -f /var/log/apache2/access.log\n";
echo " php log_analyzer_v2.php -f access.log -o json\n";
echo " php log_analyzer_v2.php -f access.log -t 20\n";
exit(0);
}
$logFile = $options['f'] ?? $options['file'] ?? null;
if (!$logFile) {
echo "错误: 请指定日志文件路径!\n\n";
echo "使用 php " . basename($argv[0]) . " -h 查看帮助\n";
exit(1);
}
$config = [
'output_format' => $options['o'] ?? $options['output'] ?? 'text',
'top_count' => intval($options['t'] ?? $options['top'] ?? 10)
];
try {
$analyzer = new AdvancedLogAnalyzer($logFile, $config);
$report = $analyzer->analyze();
echo "\n" . $report . "\n";
// 保存报告
$save = strtolower(readline("是否保存报告到文件? (y/n): "));
if ($save === 'y') {
$analyzer->saveReport($report);
}
} catch (Exception $e) {
echo "错误: " . $e->getMessage() . "\n";
exit(1);
}
}
使用说明
基本用法
# 基本分析 php log_analyzer.php /var/log/apache2/access.log # 使用增强版并输出JSON格式 php log_analyzer_v2.php -f access.log -o json # 显示Top 20数据 php log_analyzer_v2.php -f access.log -t 20 # 保存到文件 php log_analyzer.php access.log > report.txt
功能特点
- 基础统计: 请求数、IP数、流量、状态码分布
- 时间分析: 按小时统计请求量
- 错误检测: 4xx/5xx错误记录和统计
- 热门资源: Top URL和IP排行
- 用户代理: 浏览器/爬虫识别
- 性能分析: 响应时间和请求速率
- 多格式输出: 支持文本、JSON、CSV格式
- 过滤功能: 按IP、时间、状态码过滤
注意事项
- 支持Apache和Nginx默认日志格式
- 处理大文件时注意内存使用
- 可自定义过滤条件
- 支持实时分析或定时任务集成
这个脚本适合运维人员和开发人员快速分析Web服务器访问日志,发现潜在问题并优化性能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播