需要优化,考虑每次整个nginx日志文件读取内容长度很大,存在耗时并占用过多服务器资源,需要间隔时间内针对已经分析过的nginx日志不用重复分析,提供几种优化策略以减少读取文件的频率和资源占用:
1. 记录日志文件的上次分析位置
可以利用日志文件的偏移量来优化读取方式,每次只读取新增的日志内容。这种方式特别适合于增长型日志文件,例如 Nginx 的访问日志。
具体实现方法:
- 保存上次读取的偏移量:每次读取日志文件后,记录该文件的最后一个读取位置(偏移量)。
- 仅读取新增日志:下次运行时,从该偏移量继续读取新的日志内容,避免重复分析已读取的日志。
import os
import re
import subprocess
from datetime import datetime
NGINX_LOG_FILE = '/var/log/nginx/access.log'
BLACKLIST_FILE = '/etc/nginx/includes/blackListIp.conf'
OFFSET_FILE = '/tmp/nginx_log_offset.txt'
HEX_PATTERN = re.compile(r'\\x[0-9A-Fa-f]{2}')
IP_PATTERN = re.compile(r'(\d{1,3}\.){3}\d{1,3}')
def get_last_offset():
"""获取上次日志读取的偏移量"""
if os.path.exists(OFFSET_FILE):
with open(OFFSET_FILE, 'r') as f:
return int(f.read().strip())
return 0
def save_offset(offset):
"""保存当前日志读取的偏移量"""
with open(OFFSET_FILE, 'w') as f:
f.write(str(offset))
def extract_suspicious_ips(log_file):
"""从上次偏移量开始提取可疑IP"""
suspicious_ips = set()
last_offset = get_last_offset()
with open(log_file, 'r') as file:
# 移动到上次读取的位置
file.seek(last_offset)
# 逐行读取新增日志
for line in file:
if HEX_PATTERN.search(line):
match = IP_PATTERN.search(line)
if match:
ip_address = match.group(0)
suspicious_ips.add(ip_address)
# 保存当前偏移量
save_offset(file.tell())
return suspicious_ips
def update_blacklist(blacklist_file, suspicious_ips):
"""更新黑名单文件,添加新的可疑IP"""
existing_ips = set()
with open(blacklist_file, 'r') as file:
for line in file:
ip_match = IP_PATTERN.search(line)
if ip_match:
existing_ips.add(ip_match.group(0))
new_ips = suspicious_ips - existing_ips
if not new_ips:
print(f"{datetime.now()}: 没有新的可疑IP需要添加。")
return False
with open(blacklist_file, 'a') as file:
for ip in new_ips:
file.write(f"deny {ip};\n")
print(f"{datetime.now()}: 添加新的可疑IP到黑名单: {', '.join(new_ips)}")
return True
def reload_nginx():
try:
subprocess.run(['nginx', '-s', 'reload'], check=True)
print(f"{datetime.now()}: 成功重新加载Nginx配置。")
except subprocess.CalledProcessError:
print(f"{datetime.now()}: 重新加载Nginx配置失败。")
def main():
suspicious_ips = extract_suspicious_ips(NGINX_LOG_FILE)
if update_blacklist(BLACKLIST_FILE, suspicious_ips):
reload_nginx()
if __name__ == "__main__":
main()

优势:
- 减少重复分析已读取的日志条目,提高了效率。
- 偏移量记录文件较小,资源占用低。
2. 使用 Nginx 日志轮替机制
使用 Nginx 的日志轮替功能(logrotate),结合脚本只分析最近轮替出来的日志文件,避免处理过于庞大的日志文件。
具体步骤:
- 配置
logrotate,为 Nginx 日志设置合理的轮替间隔(如每天或每小时),并设置保留的旧日志数量。 - 仅分析最新的日志文件(如
/var/log/nginx/access.log),无需遍历所有旧日志。
logrotate 示例配置:
在 /etc/logrotate.d/nginx 文件中,添加以下内容:
/var/log/nginx/access.log {
daily
rotate 7
missingok
notifempty
compress
delaycompress
postrotate
[ -f /var/run/nginx.pid ] && kill -USR1 $(cat /var/run/nginx.pid)
endscript
}
优势:
- 有助于控制日志文件大小,便于定期清理和压缩历史日志。
- 减少脚本每次读取的数据量,提高效率。
3. 使用文件监控来自动触发
可以使用文件监控工具(如 inotify)来监视日志文件的变更,只有在文件变更时才触发分析脚本,从而减少无用的定时检查。
示例命令:
inotifywait -m /var/log/nginx/access.log -e modify |
while read path action file; do
/usr/bin/python3 /path/to/your/script.py
done
优势:
- 实时监控文件变化,无需定时检查。
- 仅在文件修改时触发分析,避免无用的资源消耗。
4. 使用高效的定时机制和日志采样
如无需实时检测,可以通过 低频率采样 和 多进程并发 优化性能:
- 将脚本设为每小时执行一次,而不是每几分钟,适合不需要实时检测的场景。
- 使用并发的方式对大日志文件进行分块处理,提高处理效率。
最佳组合建议
- 若需要实时检测,使用 文件偏移量记录 与 inotify 监控 是较佳选择。
- 若日常分析即可,轮替日志结合偏移量记录 是较为节省资源的选择。
当前文章价值7.65元,扫一扫支付后添加微信提供帮助!(如不能解决您的问题,可以申请退款)

你可能感兴趣的文章
分类:nginx
标签:nginx自动拦截黑客ip, python自动化脚本
评论已关闭!