解析Linux日志是系统管理和故障排查的重要任务。下面介绍几种使用JavaScript解析Linux日志的方法:
const fs = require('fs');
const readline = require('readline');
// 读取日志文件
async function parseLogFile(filePath) {
const fileStream = fs.createReadStream(filePath);
const rl = readline.createInterface({
input: fileStream,
crlfDelay: Infinity
});
// 逐行处理日志
for await (const line of rl) {
// 简单的正则表达式匹配常见的日志格式
const logPattern = /^(\w{3}\s+\d{1,2}\s\d{2}:\d{2}:\d{2})\s(\S+)\s(\S+)\[(\d+)\]:\s(.*)$/;
const match = line.match(logPattern);
if (match) {
const [_, timestamp, hostname, process, pid, message] = match;
console.log({
timestamp,
hostname,
process,
pid: parseInt(pid),
message
});
} else {
console.log('无法解析的行:', line);
}
}
}
// 使用示例
parseLogFile('/var/log/syslog').catch(console.error);
winston
处理日志const winston = require('winston');
const { combine, timestamp, printf } = winston.format;
// 创建自定义格式
const logFormat = printf(({ level, message, timestamp }) => {
return `${timestamp} [${level}]: ${message}`;
});
// 创建logger实例
const logger = winston.createLogger({
level: 'info',
format: combine(
timestamp(),
logFormat
),
transports: [
new winston.transports.File({ filename: 'application.log' })
]
});
// 记录日志
logger.info('这是一条信息日志');
logger.error('这是一条错误日志');
bunyan
处理结构化日志const bunyan = require('bunyan');
// 创建logger
const log = bunyan.createLogger({
name: 'myapp',
streams: [
{
level: 'info',
path: '/var/log/myapp.log'
}
]
});
// 记录结构化日志
log.info({ component: 'server', status: 'started' }, '服务器已启动');
function parseApacheLog(line) {
// 常见Apache日志格式
const apachePattern = /^(\S+) (\S+) (\S+) \[([\w:/]+\s[+\-]\d{4})\] "(\S+)\s?(\S+)?\s?(\S+)?" (\d{3}) (\d+)/;
const match = line.match(apachePattern);
if (match) {
const [
_,
remoteHost,
clientIdentd,
userId,
dateTime,
method,
resource,
protocol,
statusCode,
size
] = match;
return {
remoteHost,
clientIdentd,
userId,
dateTime: new Date(dateTime),
method,
resource,
protocol,
statusCode: parseInt(statusCode),
size: parseInt(size)
};
}
return null;
}
// 使用示例
const apacheLogLine = '127.0.0.1 - frank [10/Oct/2023:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326';
console.log(parseApacheLog(apacheLogLine));
对于大型日志文件,使用流处理更高效:
const fs = require('fs');
const { Transform } = require('stream');
class LogParser extends Transform {
_transform(chunk, encoding, callback) {
const lines = chunk.toString().split('\n');
for (const line of lines) {
if (line.trim()) {
// 在这里添加你的解析逻辑
const parsed = parseLogLine(line);
this.push(JSON.stringify(parsed) + '\n');
}
}
callback();
}
}
function parseLogLine(line) {
// 实现你的解析逻辑
return { line };
}
// 创建处理管道
fs.createReadStream('/var/log/large.log')
.pipe(new LogParser())
.pipe(fs.createWriteStream('parsed-logs.jsonl'));
如果你需要在浏览器中解析日志文件:
// HTML文件输入
document.getElementById('logFile').addEventListener('change', function(e) {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = function(e) {
const content = e.target.result;
const lines = content.split('\n');
lines.forEach(line => {
if (line.trim()) {
const parsed = parseLogLine(line);
console.log(parsed);
// 或者添加到DOM中显示
}
});
};
reader.readAsText(file);
});
function parseLogLine(line) {
// 实现你的解析逻辑
return { line };
}
// 统计错误级别日志
function analyzeLogLevels(logs) {
const levels = {};
logs.forEach(log => {
// 假设日志对象有level属性
const level = log.level || 'info';
levels[level] = (levels[level] || 0) + 1;
});
return levels;
}
// 查找高频错误
function findCommonErrors(logs, threshold = 5) {
const errorMessages = {};
logs
.filter(log => log.level === 'error')
.forEach(log => {
const msg = log.message.split(':')[0]; // 简单提取错误类型
errorMessages[msg] = (errorMessages[msg] || 0) + 1;
});
return Object.entries(errorMessages)
.filter(([_, count]) => count >= threshold)
.sort((a, b) => b[1] - a[1]);
}
以上方法可以根据你的具体需求进行调整和扩展。