如何用JS统计Linux日志数据

如何用JS统计Linux日志数据
最新回答
乖我要你平安

2020-11-11 21:53:45

使用JavaScript统计Linux日志数据可通过数据获取、解析、统计、输出四个步骤实现,以下是具体方法及示例代码:

一、数据获取

通过Node.js的fs模块读取日志文件,支持本地文件或远程SSH连接(需额外库如ssh2)。以下示例为本地文件读取:

const fs = require('fs');const readline = require('readline');const logFilePath = '/var/log/syslog'; // 替换为实际日志路径const fileStream = fs.createReadStream(logFilePath);const rl = readline.createInterface({ input: fileStream, crlfDelay: Infinity});二、数据解析

使用正则表达式匹配日志行中的关键字段(如IP、状态码、时间等)。示例日志格式为:IP - - [date] "GET /path HTTP/1.1" status_code解析代码:

rl.on('line', (line) => { const match = line.match(/^(d+.d+.d+.d+).*?"GET /path HTTP/1.1" (d+)/); if (match) { const ipAddress = match[1]; // 提取IP const httpStatusCode = match[2]; // 提取状态码 // 后续统计逻辑... }});

关键点

  • 正则表达式需根据实际日志格式调整(如支持POST请求或不同路径)。
  • 使用try-catch处理解析异常,避免单行错误中断整个流程。
三、数据统计

使用嵌套对象或Map存储统计结果,示例统计每个IP的各状态码出现次数:

const accessCounts = {};rl.on('line', (line) => { const match = line.match(/^(d+.d+.d+.d+).*?"GET /path HTTP/1.1" (d+)/); if (match) { const ipAddress = match[1]; const httpStatusCode = match[2]; // 初始化IP条目(若不存在) if (!accessCounts[ipAddress]) { accessCounts[ipAddress] = {}; } // 统计状态码次数 accessCounts[ipAddress][httpStatusCode] = (accessCounts[ipAddress][httpStatusCode] || 0) + 1; }});

优化建议

  • 对大规模日志,改用Map提升性能:const accessCounts = new Map();// 统计时:if (!accessCounts.has(ipAddress)) { accessCounts.set(ipAddress, new Map());}const statusMap = accessCounts.get(ipAddress);statusMap.set(httpStatusCode, (statusMap.get(httpStatusCode) || 0) + 1);
四、结果输出

在close事件中输出统计结果,支持控制台打印或文件写入:

rl.on('close', () => { console.log('访问统计结果:'); for (const [ipAddress, statusMap] of Object.entries(accessCounts)) { console.log(`IP: ${ipAddress}`); for (const [statusCode, count] of Object.entries(statusMap)) { console.log(` 状态码 ${statusCode}: ${count}次`); } } // 可选:将结果写入文件 fs.writeFileSync('stats_result.json', JSON.stringify(accessCounts, null, 2));});完整示例代码const fs = require('fs');const readline = require('readline');const logFilePath = '/var/log/nginx/access.log'; // 替换为实际路径const accessCounts = {};const fileStream = fs.createReadStream(logFilePath);const rl = readline.createInterface({ input: fileStream, crlfDelay: Infinity});rl.on('line', (line) => { // 示例正则:匹配IP、请求方法、路径、状态码 const match = line.match(/^(d+.d+.d+.d+) - - [.*] "(GET|POST) (/[^s]+) HTTP/1.1" (d+)/); if (match) { const [, ipAddress, method, path, statusCode] = match; if (!accessCounts[ipAddress]) { accessCounts[ipAddress] = { total: 0, methods: {}, paths: {}, statusCodes: {} }; } const stats = accessCounts[ipAddress]; stats.total++; stats.methods[method] = (stats.methods[method] || 0) + 1; stats.paths[path] = (stats.paths[path] || 0) + 1; stats.statusCodes[statusCode] = (stats.statusCodes[statusCode] || 0) + 1; }});rl.on('close', () => { console.log('详细统计结果:'); for (const [ip, stats] of Object.entries(accessCounts)) { console.log(`IP: ${ip}, 总请求: ${stats.total}`); console.log(' 方法分布:', stats.methods); console.log(' 路径分布:', stats.paths); console.log(' 状态码分布:', stats.statusCodes); } fs.writeFileSync('stats_detailed.json', JSON.stringify(accessCounts, null, 2));});注意事项
  1. 日志格式适配:根据实际日志调整正则表达式,例如支持ERROR级别日志或自定义字段。
  2. 性能优化:对超大规模日志(如GB级),考虑流式处理或分块读取。
  3. 错误处理:添加error事件监听:rl.on('error', (err) => console.error('读取错误:', err));
  4. 扩展性:可结合moment.js解析时间字段,或使用lodash进行数据聚合。

通过以上方法,可高效完成Linux日志的JavaScript统计分析,适用于访问量监控、错误排查等场景。