繁华依在的小站

🔍 日志管理与监控:做网站的"侦探",洞察一切

技术 作者:admin | 发布时间:2026-02-03 16:17 | 更新时间:2026-02-07 16:19 | 阅读:5 |
标签: 日志 监控 系统运维 ELK Grafana 报警

🔍 日志管理与监控:做网站的"侦探",洞察一切

网站出问题了?慢了?挂了?别慌,日志会告诉你真相!

今天我们来学习如何成为一名优秀的"网站侦探" 🕵️‍♂️


🎯 为什么需要日志和监控?

想象一下:

text
1
2
3
4
5
6
7
8
9
没有日志 = 盲人摸象
  - 不知道发生了什么
  - 出问题无从查起
  - 用户投诉才发现问题

有日志 = 开启上帝视角 👁️
  - 知道发生了什么
  - 提前发现问题
  - 主动优化性能

📊 日志的层次

应用层日志

text
1
2
3
4
Flask/Gunicorn 日志
  ├─ 访问日志:谁在什么时候访问了什么
  ├─ 错误日志:出了什么问题
  └─ 性能日志:响应时间有多长

系统层日志

text
1
2
3
4
Systemd 日志
  ├─ 服务启动/停止
  ├─ 进程崩溃记录
  └─ 资源使用情况

网络层日志

text
1
2
3
4
Nginx 日志
  ├─ 请求详情
  ├─ 响应状态
  └─ 转发记录

🗂️ 第一步:配置访问日志

Nginx 访问日志

/etc/nginx/nginx.conf

nginx
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
http {
    # 自定义日志格式
    log_format main '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" '
                    '$request_time $upstream_response_time '
                    '$upstream_addr $upstream_status';

    # 访问日志
    access_log /var/log/nginx/access.log main;

    # 错误日志
    error_log /var/log/nginx/error.log warn;
}

日志字段说明

字段 说明 示例
$remote_addr 客户端 IP 192.168.1.100
$request 请求行 GET /api/posts HTTP/1.1
$status 状态码 200
$request_time 总请求时间 0.523
$upstream_response_time 后端响应时间 0.500

Gunicorn 访问日志

gunicorn_config.py

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import multiprocessing

# 日志配置
loglevel = "info"

# 访问日志
accesslog = "logs/gunicorn_access.log"

# 错误日志
errorlog = "logs/gunicorn_error.log"

# 自定义日志格式
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s'

字段说明

  • %(h)s:客户端 IP
  • %(r)s:请求行
  • %(s)s:状态码
  • %(D)s:请求时间(微秒)

Flask 应用日志

app.py

python
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import logging
from logging.handlers import RotatingFileHandler

# 配置日志
if not os.path.exists('logs'):
    os.mkdir('logs')

# 文件日志
file_handler = RotatingFileHandler(
    'logs/app.log',
    maxBytes=10240000,  # 10MB
    backupCount=10
)
file_handler.setFormatter(logging.Formatter(
    '%(asctime)s %(levelname)s: %(message)s'
))
file_handler.setLevel(logging.INFO)

# 控制台日志
stream_handler = logging.StreamHandler()
stream_handler.setLevel(logging.INFO)

# 添加到 Flask
app.logger.addHandler(file_handler)
app.logger.addHandler(stream_handler)
app.logger.setLevel(logging.INFO)

# 使用日志
app.logger.info('应用启动')
app.logger.error('数据库连接失败')

📈 第二步:日志分析

实时查看

bash
1
2
3
4
5
6
7
8
# 查看最新日志
tail -f /var/log/nginx/access.log

# 查看最后 50 行
tail -n 50 /var/log/nginx/access.log

# 查看并高亮错误
tail -f /var/log/nginx/error.log | grep --color=auto "error"

统计访问量

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 统计总访问量
wc -l /var/log/nginx/access.log

# 按小时统计
awk '{print $4}' /var/log/nginx/access.log | \
  cut -d: -f2 | sort | uniq -c

# 统计独立 IP
awk '{print $1}' /var/log/nginx/access.log | \
  sort | uniq | wc -l

统计状态码

bash
1
2
3
4
5
6
7
8
9
# 状态码分布
awk '{print $9}' /var/log/nginx/access.log | \
  sort | uniq -c | sort -rn

# 输出示例:
#  15000 200
#    500 404
#    100 500
#     50 301

找出慢请求

bash
1
2
3
4
5
6
# 响应时间 > 1 秒的请求
awk -F'"' '$(NF-1) > 1.0 {print $0}' /var/log/nginx/access.log

# 按 IP 统计慢请求
awk -F'"' '$(NF-1) > 1.0 {print $1}' /var/log/nginx/access.log | \
  sort | uniq -c | sort -rn | head -10

找出热门 URL

bash
1
2
3
4
5
6
7
8
# 访问最多的页面
awk '{print $7}' /var/log/nginx/access.log | \
  sort | uniq -c | sort -rn | head -20

# 输出示例:
#   5000 /api/posts
#   3000 /
#   2000 /about

🔥 第三步:错误日志分析

分析 Nginx 错误

bash
1
2
3
4
5
6
# 查看最近的错误
tail -100 /var/log/nginx/error.log

# 统计错误类型
awk '{print $2}' /var/log/nginx/error.log | \
  sort | uniq -c | sort -rn

常见错误

错误 原因 解决方案
upstream timed out 后端响应慢 增加 proxy_read_timeout
connect() failed 后端服务挂了 重启后端服务
directory index of 找不到首页 检查 index 配置

分析 Gunicorn 错误

bash
1
2
3
4
5
6
# 查看 Gunicorn 错误日志
tail -f logs/gunicorn_error.log

# 统计错误类型
grep ERROR logs/gunicorn_error.log | \
  awk '{print $3}' | sort | uniq -c

🔄 第四步:日志轮转

为什么需要轮转?

text
1
2
3
4
5
6
7
8
9
不轮转 = 💣 炸弹
  - 日志文件无限增长
  - 磁盘被占满
  - 系统崩溃

轮转 = ✅ 安全
  - 定期归档旧日志
  - 压缩节省空间
  - 自动删除过期日志

Logrotate 配置

/etc/logrotate.d/flask-blog

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/var/www/blog/logs/*.log {
    daily           # 每天轮转
    missingok       # 文件不存在不报错
    rotate 14       # 保留 14 天
    compress        # 压缩旧日志
    delaycompress   # 延迟一天压缩
    notifempty      # 空文件不轮转
    create 0644 www-data www-data
    sharedscripts
    postrotate
        # 重启应用(如果需要)
        systemctl reload flask-blog > /dev/null 2>&1 || true
    endscript
}

Nginx 日志轮转

/etc/logrotate.d/nginx

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
/var/log/nginx/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 nginx nginx
    sharedscripts
    prerotate
        if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
            run-parts /etc/logrotate.d/httpd-prerotate; \
        fi
    endscript
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}

测试 Logrotate

bash
1
2
3
4
5
# 调试模式(不实际执行)
sudo logrotate -d /etc/logrotate.d/flask-blog

# 强制执行
sudo logrotate -f /etc/logrotate.d/flask-blog

📊 第五步:监控指标

系统资源监控

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# CPU 和内存使用
htop

# 磁盘使用
df -h

# 进程监控
ps aux | grep gunicorn

# 网络连接
netstat -anp | grep :5000

应用性能监控

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 统计平均响应时间
awk -F'"' '{print $(NF-1)}' /var/log/nginx/access.log | \
  awk '{sum+=$1; count++} END {print sum/count}'

# 统计 QPS(每秒请求数)
awk '{print $4}' /var/log/nginx/access.log | \
  cut -d: -f2 | sort | uniq -c

# 统计并发数
netstat -an | grep :5000 | grep ESTABLISHED | wc -l

自定义监控脚本

monitor.sh

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#!/bin/bash

# 颜色定义
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'

# 检查服务状态
check_service() {
    if systemctl is-active --quiet "$1"; then
        echo -e "${GREEN}$1 运行中${NC}"
    else
        echo -e "${RED}$1 已停止${NC}"
    fi
}

# 检查端口
check_port() {
    if netstat -tuln | grep -q ":$1 "; then
        echo -e "${GREEN}✓ 端口 $1 监听中${NC}"
    else
        echo -e "${RED}✗ 端口 $1 未监听${NC}"
    fi
}

# 检查磁盘空间
check_disk() {
    USAGE=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
    if [ $USAGE -gt 80 ]; then
        echo -e "${RED}⚠ 磁盘使用: ${USAGE}%${NC}"
    else
        echo -e "${GREEN}✓ 磁盘使用: ${USAGE}%${NC}"
    fi
}

# 主函数
main() {
    echo "=== 系统监控 $(date) ==="
    echo ""
    echo "服务状态:"
    check_service "flask-blog"
    check_service "nginx"
    check_service "frpc"
    echo ""
    echo "端口检查:"
    check_port 5000
    check_port 80
    echo ""
    check_disk
    echo ""
}

main

🚨 第六步:告警系统

简单告警脚本

alert.sh

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
#!/bin/bash

# 阈值
CPU_THRESHOLD=80
DISK_THRESHOLD=80
MEMORY_THRESHOLD=80

# 检查 CPU
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)
if (( $(echo "$CPU_USAGE > $CPU_THRESHOLD" | bc -l) )); then
    echo "⚠️ CPU 使用率过高: ${CPU_USAGE}%" | mail -s "告警" admin@example.com
fi

# 检查磁盘
DISK_USAGE=$(df / | awk 'NR==2 {print $5}' | tr -d '%')
if [ $DISK_USAGE -gt $DISK_THRESHOLD ]; then
    echo "⚠️ 磁盘使用率过高: ${DISK_USAGE}%" | mail -s "告警" admin@example.com
fi

系统级监控工具

1. Monit

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# 安装
sudo apt install monit -y

# 配置
sudo tee /etc/monit/monitrc.d/flask-blog > /dev/null << 'EOF'
check process flask-blog matching gunicorn
    start program = "/bin/systemctl start flask-blog"
    stop program = "/bin/systemctl stop flask-blog"
    if failed port 5000 protocol http then restart
    if 5 restarts within 5 cycles then timeout
EOF

# 启动
sudo systemctl enable monit
sudo systemctl start monit

2. Prometheus + Grafana

架构

text
1
应用 → Exporter → Prometheus → Grafana

安装 Prometheus

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
# 安装
sudo apt install prometheus -y

# 配置目标
sudo tee /etc/prometheus/prometheus.yml > /dev/null << 'EOF'
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['localhost:9100']
EOF

# 启动
sudo systemctl enable prometheus
sudo systemctl start prometheus

📱 第七步:可视化监控

Grafana Dashboard

bash
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 安装 Grafana
sudo apt install grafana -y

# 启动
sudo systemctl enable grafana-server
sudo systemctl start grafana-server

# 访问
http://localhost:3000
# 默认用户名/密码:admin/admin

常用指标面板

  • QPS(每秒请求数)
  • 响应时间
  • 错误率
  • CPU 使用率
  • 内存使用率
  • 磁盘使用率
  • 网络流量

🔍 第八步:实战案例

场景:网站突然变慢

步骤 1:检查系统资源

bash
1
2
htop
# 发现:CPU 100%,内存正常

步骤 2:查看日志

bash
1
2
tail -f /var/log/nginx/access.log
# 发现:大量请求到同一个 URL

步骤 3:分析请求

bash
1
2
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head -5
# 发现:/api/heavy 被频繁访问

步骤 4:定位问题

bash
1
2
3
# 查看 Gunicorn 日志
tail -f logs/gunicorn_error.log
# 发现:数据库查询很慢

解决方案

python
1
2
3
4
5
# 添加缓存
@lru_cache(maxsize=128)
def heavy_computation():
    # ... 耗时操作
    pass

📋 监控检查清单

基础监控

  • [ ] 访问日志正常记录
  • [ ] 错误日志正常记录
  • [ ] 日志轮转已配置
  • [ ] 磁盘空间监控

应用监控

  • [ ] 服务状态监控
  • [ ] 响应时间监控
  • [ ] 错误率监控
  • [ ] 并发数监控

告警配置

  • [ ] 服务停止告警
  • [ ] 磁盘满告警
  • [ ] 高负载告警
  • [ ] 异常错误告警

🎉 总结

日志和监控的重要性:

  1. 发现问题 → 从用户抱怨到主动发现
  2. 定位问题 → 快速找到根本原因
  3. 预防问题 → 提前发现趋势
  4. 优化性能 → 数据驱动优化

记住:

"没有监控的系统就像盲人开夜车,迟早要出事!" 🚗💥


🔗 相关工具

  • 日志管理:Logstash, Fluentd, Filebeat
  • 监控系统:Prometheus, Zabbix, Nagios
  • 可视化:Grafana, Kibana
  • APM:New Relic, Datadog, Sentry

下一篇:自动化备份策略,别让你的数据丢了!💾

评论 (0)

暂无评论,快来抢沙发吧~

发表评论