Linux 日志监控与报警系统实操
1.日志监控基础
-
监控文件变化:
-
tail -f
:实时查看文件末尾的变化。 -
tail -n
:指定查看最近的 N 行。
-
-
结合管道过滤关键内容:
-
配合
grep
提取特定关键字。
-
例子:
tail -f /var/log/syslog | grep "error"
2.日志文件滚动
-
了解日志文件的滚动机制(如日志按大小或时间切割)。
-
使用
logrotate
进行日志管理。
3.实时报警机制
-
结合
awk
提取特定模式并触发报警。 -
邮件报警:
-
使用
mail
或sendmail
命令发送邮件。
-
-
终端提示:
-
使用
echo
和notify-send
。
-
例子:
tail -f application.log | awk '/ERROR/ {print "Error detected: "$0}'
4.复杂监控场景
-
多关键字匹配与分级报警。
-
监控多文件并聚合结果。
实验例子
实验 1: 简单日志监控
目标:实时监控一个日志文件并提取含有 "ERROR" 的行。
实验代码:
#!/bin/bash
logfile="application.log"
if [[ ! -f $logfile ]]; then
echo "Log file not found: $logfile"
exit 1
fi
echo "Monitoring $logfile for 'ERROR'..."
tail -f $logfile | grep "ERROR"
实验 2: 动态监控日志并发送报警
目标:检测日志文件中的错误信息,并在终端显示报警。
实验代码:
#!/bin/bash
logfile="application.log"
if [[ ! -f $logfile ]]; then
echo "Log file not found: $logfile"
exit 1
fi
monitor_log() {
tail -f $logfile | while read line; do
if echo "$line" | grep -q "ERROR"; then
echo "[ALERT] $(date): $line"
fi
done
}
monitor_log
实验 3: 日志关键字分级报警
目标:根据日志内容分类报警,如 "ERROR" 触发高优先级报警,"WARNING" 触发普通报警。
实验代码:
#!/bin/bash
logfile="application.log"
if [[ ! -f $logfile ]]; then
echo "Log file not found: $logfile"
exit 1
fi
tail -f $logfile | while read line; do
if echo "$line" | grep -q "ERROR"; then
echo "[HIGH PRIORITY ALERT] $(date): $line"
elif echo "$line" | grep -q "WARNING"; then
echo "[Warning] $(date): $line"
fi
done
实验 4: 监控多日志文件
目标:同时监控多个日志文件,并合并结果。
实验代码:
#!/bin/bash
logfiles=("/var/log/syslog" "/var/log/auth.log")
for logfile in "${logfiles[@]}"; do
if [[ -f $logfile ]]; then
tail -f $logfile | awk -v log=$logfile '{print "["log"] "$0}' &
else
echo "File not found: $logfile"
fi
done
wait
实验 5: 定制报警系统
目标:基于日志信息发送邮件通知。
实验代码:
#!/bin/bash
logfile="application.log"
email="admin@example.com"
if [[ ! -f $logfile ]]; then
echo "Log file not found: $logfile"
exit 1
fi
tail -f $logfile | while read line; do
if echo "$line" | grep -q "CRITICAL"; then
echo "Critical alert detected: $line" | mail -s "Critical Alert" $email
echo "Email sent for alert: $line"
fi
done
实操
-
编写脚本监控
/var/log/syslog
,提取含有 "Failed" 的行并统计次数。
#!/bin/bash
logfile="/var/log/syslog"
count=0
if [[ ! -f $logfile ]]; then
echo "Log file not found: $logfile"
exit 1
fi
echo "Monitoring $logfile for 'Failed'..."
tail -f $logfile | while read line; do
if echo "$line" | grep -q "Failed"; then
count=$((count + 1))
echo "$line"
echo "Total 'Failed' entries: $count"
fi
done
-
实现一个脚本监控指定文件夹的文件增长情况。
#!/bin/bash
monitor_dir="/path/to/your/directory"
if [[ ! -d $monitor_dir ]]; then
echo "Directory not found: $monitor_dir"
exit 1
fi
echo "Monitoring file changes in $monitor_dir..."
prev_count=$(ls "$monitor_dir" | wc -l)
while true; do
current_count=$(ls "$monitor_dir" | wc -l)
if [[ $current_count -ne $prev_count ]]; then
echo "$(date): File count changed from $prev_count to $current_count"
prev_count=$current_count
fi
sleep 2
done
-
将实验 3 的代码改进,支持通过配置文件指定关键字和报警级别。
#!/bin/bash
logfile="application.log"
config_file="keywords.conf"
if [[ ! -f $logfile ]]; then
echo "Log file not found: $logfile"
exit 1
fi
if [[ ! -f $config_file ]]; then
echo "Config file not found: $config_file"
exit 1
fi
declare -A keywords
while IFS=: read -r keyword level; do
keywords["$keyword"]=$level
done < "$config_file"
tail -f $logfile | while read line; do
for keyword in "${!keywords[@]}"; do
if echo "$line" | grep -q "$keyword"; then
echo "[${keywords[$keyword]} PRIORITY] $(date): $line"
fi
done
done
-
使用
tail -f
和awk
实现实时日志监控,统计日志中每分钟的访问次数。
#!/bin/bash
logfile="access.log"
if [[ ! -f $logfile ]]; then
echo "Log file not found: $logfile"
exit 1
fi
echo "Monitoring $logfile for access counts per minute..."
tail -f $logfile | awk '
{
timestamp = substr($4, 2, 17) # 提取时间戳,格式化为 "dd/MMM/yyyy:HH:mm"
split(timestamp, time_parts, ":")
minute = time_parts[1] ":" time_parts[2] # 仅保留到分钟
access_counts[minute]++
print "Access count for " minute ": " access_counts[minute]
}'
-
编写脚本实现对超过指定大小的日志文件进行自动归档和压缩。
#!/bin/bash
logfile="application.log"
max_size=1048576 # 1 MB in bytes
archive_dir="archives"
mkdir -p "$archive_dir"
while true; do
if [[ -f $logfile ]]; then
log_size=$(stat -c%s "$logfile")
if (( log_size > max_size )); then
timestamp=$(date +'%Y%m%d_%H%M%S')
mv "$logfile" "$archive_dir/application_$timestamp.log"
gzip "$archive_dir/application_$timestamp.log"
echo "Archived and compressed $logfile at $timestamp"
> "$logfile" # 清空原日志文件
fi
fi
sleep 10
done