悠悠楠杉
Linux日志怎么切割:通过自定义脚本按网络连接实现精细化管理
在现代服务器运维中,日志是排查问题、监控系统状态和分析安全事件的核心依据。随着服务运行时间的增长,日志文件会迅速膨胀,不仅占用大量磁盘空间,还会导致日志检索效率低下。虽然logrotate是Linux系统中常用的日志轮转工具,但在某些特定场景下——比如需要根据网络连接(如源IP、目标端口、协议类型)对日志进行分类存储时,标准工具就显得力不从心了。
这时候,自定义脚本就成了更灵活、更具针对性的解决方案。本文将带你一步步实现一个基于网络连接信息的日志切割脚本,让日志管理真正“按需而动”。
首先,我们要明确需求背景。假设你管理着一台Web服务器,每天产生大量的访问日志(如Nginx的access.log),其中包含了客户端IP、请求路径、响应状态码以及用户代理等信息。出于安全审计或流量分析的目的,你希望将来自不同地区或可疑IP段的请求日志单独保存,便于后续追踪。这种情况下,简单的按时间或大小切割已无法满足要求,必须引入内容识别机制。
我们的思路是:编写一个Bash脚本,实时读取原始日志文件,逐行解析每条记录中的网络连接信息(例如源IP地址),然后根据预设规则将其写入不同的子日志文件中。例如,所有来自192.168.1.0/24网段的请求归入internal.log,而来自外部高风险IP的请求则存入suspicious.log。
脚本的核心逻辑如下:
bash
!/bin/bash
LOGSOURCE="/var/log/nginx/access.log" OUTPUTDIR="/var/log/split_logs"
确保输出目录存在
mkdir -p $OUTPUT_DIR
实时监控日志文件新增内容
tail -F $LOGSOURCE | while read line; do # 提取源IP(假设日志格式为:IP - - [time] "GET / HTTP/1.1" ...) clientip=$(echo "$line" | awk '{print $1}')
# 判断IP所属类别并写入对应文件
if [[ $client_ip =~ ^192\.168\.1\.[0-9]{1,3}$ ]]; then
echo "$line" >> "$OUTPUT_DIR/internal.log"
elif [[ $client_ip =~ ^10\. ]]; then
echo "$line" >> "$OUTPUT_DIR/private.log"
elif [[ $client_ip =~ ^(1\.1\.1\.1|8\.8\.8\.8)$ ]]; then
echo "$line" >> "$OUTPUT_DIR/dns_query.log"
else
echo "$line" >> "$OUTPUT_DIR/external.log"
fi
done
这个脚本使用tail -F持续监听日志文件的变化,避免遗漏新写入的内容。通过正则表达式匹配IP地址段,实现了基于网络拓扑结构的日志分流。你可以根据实际网络环境调整匹配规则,甚至引入外部IP地理数据库(如GeoIP)来实现按国家或城市分类。
当然,直接运行该脚本会占用一个终端会话。为了保证其长期稳定运行,建议将其作为系统服务管理。可以创建一个systemd unit文件(如/etc/systemd/system/log-splitter.service):
ini
[Unit]
Description=Custom Log Splitter by Network Connection
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/split-log-by-ip.sh
Restart=always
User=root
[Install]
WantedBy=multi-user.target
启用并启动服务后,脚本将在后台持续运行,并在系统重启后自动恢复。
此外,还需考虑性能影响。对于高并发场景,频繁的文件写操作可能成为瓶颈。优化手段包括:使用缓冲写入、合并短时间内的相同目标写操作,或改用日志收集框架(如rsyslog配合模板)实现更高效的处理。
通过这种方式,我们不仅实现了日志的智能切割,还为后续的安全分析打下了基础。例如,可以针对suspicious.log设置告警规则,或定期生成访问来源报告。
日志管理的本质不是“存”,而是“用”。只有让日志变得可读、可查、可追溯,它才能真正发挥价值。而自定义脚本,正是打通这一链条的关键钥匙。
