服务器出了问题?Nginx 日志几万行不知道怎么下手?今天我们做一个命令行日志分析工具,输入一个日志文件路径,自动解析出 Top 10 访问 IP、HTTP 状态码分布、请求方法统计和热门 URL。
安装 OpenCode(opencode.ai 下载安装包)
确保 Python 3.6+ 已安装:python --version
准备一个测试用的 Nginx 日志文件(本文使用 access.log)
我先用一句话描述需求,让 OpenCode 生成初始代码。
我对 OpenCode 说:
> 用 Python 写一个命令行日志分析脚本,能解析 Nginx access log 格式,接收一个文件路径参数,打印出总请求数、Top 10 访问 IP 和 HTTP 状态码分布。用标准库,不要第三方依赖。
OpenCode 的响应:
OpenCode 先扫描了项目目录,确认没有冲突文件,然后直接生成了 log_analyzer.py,包含:
argparse 处理命令行参数Counter 做统计分析代码一气呵成,无需修改即可运行。
> 关键要点: 提示词里明确说了"标准库、零依赖",这样 OpenCode 就不会去 pip install 第三方包。
运行了一遍基础版,输出不错,但我想要更灵活的导出格式。
我对 OpenCode 说:
> 给脚本加一个 --json 参数,当指定时输出 JSON 格式而不是表格。JSON 里包含 total、top_ips、status_codes、methods 四个字段。
OpenCode 的响应:
OpenCode 读了现有代码,理解了输出逻辑,然后:
在 argparse 里加了 --json 参数
新增一个格式化分支,用 json.dumps 输出
保持原有表格输出不变
改动精准,只动了 show_stats 函数和 main 里的参数定义。
> 关键要点: 给已有代码加功能时,OpenCode 会先读文件再改,不会推倒重来。你可以放心地"追加需求"。
代码已经能用,但还没处理文件不存在的情况。
我对 OpenCode 说:
> 加上错误处理:文件不存在时给出友好提示并退出,其他异常也捕获并输出错误信息。
OpenCode 的响应:
OpenCode 在 main() 里包了一层 try/except,分别捕获 FileNotFoundError 和通用 Exception,并设置了 sys.exit(1) 退出码。改动 10 行。
> 关键要点: OpenCode 善于做"防御性编程"补充,你不用一条条列边界情况,说一句"加上错误处理"就够了。
代码完成,我需要确认效果。
我对 OpenCode 说:
> 帮我生成一个测试用的 sample.log,包含 20 条模拟 Nginx 日志,覆盖不同 IP、状态码和 URL。
OpenCode 的响应:
OpenCode 生成了 sample.log,包含 GET/POST 请求、200/301/404/500 等状态码,以及几个不同的 IP 地址。然后直接运行 python log_analyzer.py sample.log 验证了输出。
整个过程从开始到结束,实际只用了 4 分钟。
import sys
import json
import argparse
from collections import Counter
import re
LOG_PATTERN = re.compile(
r'(?P<ip>\S+)\s+\S+\s+\S+\s+\[(?P<time>[^\]]+)\]\s+'
r'"(?P<method>\S+)\s+(?P<url>\S+)\s+\S+"\s+'
r'(?P<status>\d+)\s+(?P<size>\S+)\s+"(?P<referer>[^"]*)"\s+"(?P<ua>[^"]*)"'
)
def parse_log(line):
m = LOG_PATTERN.match(line.strip())
if m:
return m.groupdict()
return None
def analyze(filepath):
entries = []
with open(filepath, 'r', encoding='utf-8') as f:
for line in f:
entry = parse_log(line)
if entry:
entries.append(entry)
return entries
def show_stats(entries, fmt='table'):
ips = Counter(e['ip'] for e in entries)
statuses = Counter(e['status'] for e in entries)
methods = Counter(e['method'] for e in entries)
urls = Counter(e['url'] for e in entries)
if fmt == 'json':
print(json.dumps({
'total': len(entries),
'top_ips': ips.most_common(10),
'status_codes': dict(statuses),
'methods': dict(methods),
'top_urls': urls.most_common(10),
}, indent=2, ensure_ascii=False))
else:
print(f"\n{'='*60}")
print(f" 日志分析报告")
print(f"{'='*60}")
print(f"\n总请求数: {len(entries)}")
print(f"\n{'─'*40}")
print(f" Top 10 IP")
print(f"{'─'*40}")
for ip, count in ips.most_common(10):
print(f" {ip:<20s} {count}")
print(f"\n{'─'*40}")
print(f" 状态码分布")
print(f"{'─'*40}")
for code, count in statuses.most_common():
print(f" {code:<20s} {count}")
print(f"\n{'─'*40}")
print(f" 请求方法")
print(f"{'─'*40}")
for method, count in methods.most_common():
print(f" {method:<20s} {count}")
print(f"\n{'─'*40}")
print(f" Top 10 URL")
print(f"{'─'*40}")
for url, count in urls.most_common(10):
print(f" {url:<50s} {count}")
print()
def main():
parser = argparse.ArgumentParser(description='命令行日志分析工具')
parser.add_argument('file', help='日志文件路径')
parser.add_argument('--json', action='store_true', help='JSON格式输出')
args = parser.parse_args()
try:
entries = analyze(args.file)
fmt = 'json' if args.json else 'table'
show_stats(entries, fmt)
except FileNotFoundError:
print(f'错误: 文件 "{args.file}" 不存在')
sys.exit(1)
except Exception as e:
print(f'错误: {e}')
sys.exit(1)
if __name__ == '__main__':
main()
这个工具如果手写,查正则、写 argparse、调格式,磕磕绊绊大概要 20 分钟。用 OpenCode 只需要 4 分钟,且每个步骤都能实时看到结果、随时追加需求。
OpenCode 的优势不在于"一次生成完美代码",而在于分步迭代——你先描述核心需求,跑起来,再逐步完善。这和你自己写代码的思路是一样的,区别在于:你只需要说,不需要敲。
感兴趣的话,试试用 OpenCode 给你的日常运维脚本加上 JSON 输出和错误处理,你会发现那些"懒得加"的功能,现在一句话就够了。