2026-05-25 21:49:22 +08:00
2026-01-04 19:17:33 +08:00
2026-01-04 19:17:33 +08:00
2026-01-04 20:55:28 +08:00

家庭日报系统

专注于家庭生活的轻量级日报系统使用Django框架开发。

功能特性

核心功能模块

1. 阅读记录管理

  • 支持添加、编辑、删除阅读记录
  • 阅读类型分类管理(如:书籍、文章、论文等)
  • 记录阅读标题、来源、进度
  • 支持添加阅读笔记
  • 支持文件上传(阅读相关资料)
  • 支持查看昨日和今日的阅读记录

2. 感悟记录管理

  • 支持添加、编辑、删除感悟记录
  • 支持选择发言人(家庭成员)
  • 感悟内容记录
  • 支持文件上传(感悟相关资料)
  • 支持查看昨日和今日的感悟记录

3. 汇总记录管理

  • 支持添加、编辑、删除汇总记录
  • 汇总分类管理(如:新闻、知识、生活等)
  • 支持选择发言人和来源
  • 汇总内容记录
  • 支持文件上传

4. 家庭事项管理

  • 支持添加、编辑、删除家庭事项
  • 自定义事项类型
  • 设置优先级(高、中、低)
  • 设置状态(待处理、已完成等)
  • 设置截止日期
  • 支持按优先级和截止日期排序

5. 今日计划管理

  • 支持添加、编辑、删除今日计划
  • 设置计划类型
  • 设置优先级
  • 设置状态(待处理、已完成)
  • 支持状态快速切换
  • 支持选择发言人
  • 按优先级排序显示

6. 报告生成与查看

  • 自动生成每日家庭日报
  • 报告内容包括:
    • 昨日阅读记录汇总
    • 昨日感悟记录汇总
    • 昨日汇总记录
    • 今日计划列表
    • 家庭事项统计
  • 支持查看历史报告
  • 支持选择不同日期查看报告

7. PDF报告生成

  • 使用WeasyPrint生成PDF格式报告
  • 支持报告预览HTML格式与PDF样式一致
  • 支持下载PDF文件
  • PDF文件自动保存到服务器
  • 支持查看历史PDF文件列表

8. 邮件发送功能

  • 支持SMTP邮件发送
  • 邮件包含PDF报告附件
  • 支持定时发送通过Celery Beat
  • 支持手动发送
  • 可配置发送时间
  • 支持多个收件人

9. 系统配置

  • SMTP服务器配置
  • 发送时间设置
  • 发件人邮箱配置
  • 收件人邮箱配置
  • 通过Web界面进行配置

10. 后台管理界面

  • 完整的Django Admin后台
  • 访问路径:/houtai
  • 管理所有数据模型
  • 管理用户和权限

数据模型

模型 说明 主要字段
ReadingType 阅读记录类型 name
FamilyTaskType 家庭事项类型 name
Priority 优先级 name
Status 状态 name
PlanType 今日计划类型 name
FamilyMember 家庭成员 name
ReadingRecord 阅读记录 date, type, title, source, progress, note, file
InsightRecord 感悟记录 date, content, speaker, file
Summary 汇总记录 date, category, speaker, content, source, file
FamilyTask 家庭事项 type, content, priority, status, deadline
TodayPlan 今日计划 date, content, speaker, priority, type, status
SystemConfig 系统配置 smtp_server, send_time, recipient_email等

异步任务

系统使用Celery处理异步任务

  • generate_daily_pdf_report每日PDF报告生成
  • send_daily_report:每日邮件发送
  • 依赖Redis作为消息代理
  • 支持定时任务调度

技术栈

  • Python 3.10+
  • Django 4.2+
  • Bootstrap 5
  • SQLite开发环境
  • PostgreSQL/MySQL生产环境
  • Gunicorn + Nginx生产部署

快速开始

安装依赖

pip install -r requirements.txt

运行开发服务器

python manage.py runserver

访问系统

打开浏览器访问:http://127.0.0.1:8000

数据库迁移指南

基本迁移流程

  1. 生成迁移文件:

    python manage.py makemigrations
    
  2. 查看迁移文件内容(重要!):

    cat core/migrations/000x_xxx.py
    
  3. 应用迁移:

    python manage.py migrate
    

当数据库有数据时增加字段

问题说明

当数据库中已有数据时通过Django的migrate命令增加新字段不会删除原有数据,但需要注意以下几点:

  1. 如果新字段设置为非空null=False, blank=False),则必须提供默认值,否则迁移会失败
  2. 如果新字段设置为可空null=True, blank=True则迁移会自动执行原有记录的新字段值为NULL

正确部署流程

  1. 在开发环境测试

    • 首先在开发环境生成迁移文件
    • 检查迁移文件内容,确保:
      • 新字段设置为可空(null=True, blank=True),或者
      • 新字段提供了合理的默认值
    • 在开发环境执行迁移,测试功能是否正常
  2. 备份生产数据库(重要!):

    # PostgreSQL示例
    pg_dump -U username -d dbname > backup_$(date +%Y%m%d_%H%M%S).sql
    
    # MySQL示例
    mysqldump -u username -p dbname > backup_$(date +%Y%m%d_%H%M%S).sql
    
  3. 在生产环境执行迁移

    # 进入项目目录
    cd /path/to/diary-family
    
    # 激活虚拟环境
    source venv/bin/activate
    
    # 生成迁移文件(如果在开发环境已生成,可跳过)
    python manage.py makemigrations
    
    # 应用迁移
    python manage.py migrate
    
  4. 验证迁移结果

    • 检查应用是否正常运行
    • 验证新功能是否可用
    • 检查数据是否完整

示例增加阅读笔记note字段

  1. 在模型中添加字段(core/models.py

    # 正确的做法:设置为可空字段
    note = models.TextField(blank=True, null=True, verbose_name="阅读笔记")
    
    # 或者:提供默认值
    note = models.TextField(default="", blank=True, verbose_name="阅读笔记")
    
  2. 生成迁移文件:

    python manage.py makemigrations
    
  3. 检查迁移文件,确保新字段设置正确:

    # 迁移文件示例0003_readingrecord_note.py
    class Migration(migrations.Migration):
        dependencies = [
            ('core', '0002_xxx'),
        ]
    
        operations = [
            migrations.AddField(
                model_name='readingrecord',
                name='note',
                field=models.TextField(blank=True, null=True, verbose_name='阅读笔记'),
            ),
        ]
    
  4. 应用迁移:

    python manage.py migrate
    

CSV数据导入指南

生成CSV文件

项目包含一个generate_import_csv.py脚本用于生成符合数据库表结构的CSV文件并导入数据。

  1. 生成CSV文件

    python generate_import_csv.py
    
  2. 生成的CSV文件

    • reading_type.csv - 阅读记录类型
    • insight_record.csv - 感悟记录
    • reading_record.csv - 阅读记录

CSV文件格式说明

reading_type.csv阅读记录类型

字段名 类型 说明
name 字符串 阅读类型名称(如:书籍、文章、论文等)

insight_record.csv感悟记录

字段名 类型 说明
date 日期 记录日期格式YYYY-MM-DD
content 文本 感悟内容

reading_record.csv阅读记录

字段名 类型 说明
date 日期 记录日期格式YYYY-MM-DD
type_id 整数 阅读类型ID关联reading_type表的id字段
title 字符串 阅读标题
source 字符串 阅读来源
progress 字符串 阅读进度(如:已完成、进行中、未开始)
note 文本 阅读笔记

自定义CSV数据

你可以手动编辑生成的CSV文件添加或修改数据然后再次运行导入脚本将数据导入到数据库。

数据导入

脚本会自动将CSV数据导入到数据库中导入流程

  1. 清空ReadingType表的现有数据避免类型ID冲突
  2. 导入ReadingType数据
  3. 导入InsightRecord数据
  4. 导入ReadingRecord数据

验证导入结果

可以使用Django shell查询数据库验证数据是否正确导入

python -c "import os; os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'diary_family.settings'); import django; django.setup(); from core.models import ReadingType, InsightRecord, ReadingRecord; print('ReadingType数量:', ReadingType.objects.count()); print('InsightRecord数量:', InsightRecord.objects.count()); print('ReadingRecord数量:', ReadingRecord.objects.count()); print('ReadingType数据:', [rt.name for rt in ReadingType.objects.all()])"

生产部署

使用Gunicorn + Nginx

  1. 安装Gunicorn

    pip install gunicorn
    
  2. 启动Gunicorn

    gunicorn diary_family.wsgi:application --bind 0.0.0.0:8000
    
  3. 配置Nginx/etc/nginx/sites-available/diary-family

    server {
        listen 80;
        server_name example.com;
    
        location / {
            proxy_pass http://127.0.0.1:8000;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    
        location /static/ {
            alias /path/to/diary-family/static/;
        }
    
        location /media/ {
            alias /path/to/diary-family/media/;
        }
    }
    
  4. 启用Nginx配置

    ln -s /etc/nginx/sites-available/diary-family /etc/nginx/sites-enabled/
    systemctl restart nginx
    

Redis服务器部署必需

家庭日报系统使用Celery进行异步任务处理如PDF生成、邮件发送而Celery依赖Redis作为消息代理和结果后端。在生产环境中必须部署Redis服务器

1. 安装Redis服务器

在Ubuntu服务器上安装Redis

# 更新包管理器
sudo apt update

# 安装Redis服务器
sudo apt install redis-server -y

# 启动Redis服务
sudo systemctl start redis-server

# 设置Redis开机自启
sudo systemctl enable redis-server

# 检查Redis服务状态
sudo systemctl status redis-server

2. 配置Redis安全设置生产环境重要

编辑Redis配置文件以增强安全性

# 备份原始配置文件
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.backup

# 编辑Redis配置文件
sudo nano /etc/redis/redis.conf

在配置文件中进行以下修改:

# 1. 绑定到本地地址或特定IP禁止外部访问
bind 127.0.0.1

# 2. 设置强密码(强烈建议)
requirepass your_secure_password_here

# 3. 禁用危险命令(防止误操作)
rename-command FLUSHDB ""
rename-command FLUSHALL ""
rename-command CONFIG ""

# 4. 限制内存使用(根据服务器内存调整)
maxmemory 256mb
maxmemory-policy allkeys-lru

# 5. 启用持久化
save 900 1
save 300 10
save 60 10000

保存并重启Redis服务

# 重启Redis使配置生效
sudo systemctl restart redis-server

# 验证Redis是否正常运行
redis-cli ping

3. 测试Redis连接

验证Redis是否可以正常连接

基本连接测试:

# 测试无密码连接(如果设置了密码,应该失败)
redis-cli ping

# 使用密码连接(应该成功)
redis-cli -a your_secure_password_here ping

# 测试基本操作
redis-cli -a your_secure_password_here set test_key "hello"
redis-cli -a your_secure_password_here get test_key
redis-cli -a your_secure_password_here del test_key

高级测试:

# 测试Redis信息
redis-cli -a your_secure_password_here info

# 测试内存使用
redis-cli -a your_secure_password_here info memory

# 测试持久化状态
redis-cli -a your_secure_password_here info persistence

# 测试连接数
redis-cli -a your_secure_password_here info clients

# 性能测试设置100个键
for i in {1..100}; do redis-cli -a your_secure_password_here set "perf:$i" "value$i" > /dev/null; done

# 性能测试获取100个键
for i in {1..100}; do redis-cli -a your_secure_password_here get "perf:$i" > /dev/null; done

# 清理测试数据
for i in {1..100}; do redis-cli -a your_secure_password_here del "perf:$i" > /dev/null; done

使用Python测试脚本

项目提供了专门的测试脚本可以全面测试Redis和Celery集成

# 运行完整的Redis和Celery测试
python test_redis_celery.py

# 测试输出示例:
# 2024-01-15 10:30:00 | INFO     | 开始测试Redis连接...
# 2024-01-15 10:30:01 | SUCCESS  | Redis连接测试通过
# 2024-01-15 10:30:02 | INFO     | 开始测试Celery与Redis集成...
# 2024-01-15 10:30:03 | SUCCESS  | Celery与Redis集成测试通过
# 2024-01-15 10:30:04 | INFO     | 开始测试Redis性能...
# 2024-01-15 10:30:05 | SUCCESS  | Redis性能优秀
# 2024-01-15 10:30:06 | SUCCESS  | 所有测试通过生产环境Redis和Celery配置正确。

快速验证命令:

# 一键验证Redis服务状态
sudo systemctl status redis-server --no-pager

# 验证Redis端口监听
sudo netstat -tlnp | grep 6379

# 验证Redis进程
ps aux | grep redis-server

# 验证Redis日志
sudo tail -n 10 /var/log/redis/redis-server.log

4. 配置Django项目使用Redis

在Django项目的settings.py更新Celery配置以使用Redis

# 生产环境Redis配置带密码
CELERY_BROKER_URL = 'redis://:your_secure_password_here@localhost:6379/0'
CELERY_RESULT_BACKEND = 'redis://:your_secure_password_here@localhost:6379/0'

5. 验证Celery与Redis连接

测试Celery是否可以正常连接到Redis

# 激活虚拟环境
source /path/to/venv/bin/activate

# 测试Celery连接
celery -A diary_family inspect ping

# 查看Celery worker状态
celery -A diary_family status

# 查看任务队列
celery -A diary_family inspect active
celery -A diary_family inspect scheduled

6. Redis监控和维护

监控Redis性能

# 查看Redis基本信息
redis-cli -a your_secure_password_here info

# 查看内存使用情况
redis-cli -a your_secure_password_here info memory

# 查看连接数
redis-cli -a your_secure_password_here info clients

# 查看持久化状态
redis-cli -a your_secure_password_here info persistence

定期维护:

# 备份Redis数据
sudo cp /var/lib/redis/dump.rdb /backup/redis/dump.rdb.$(date +%Y%m%d)

# 清理过期键
redis-cli -a your_secure_password_here --scan --pattern "*" | xargs redis-cli -a your_secure_password_here del

# 查看慢查询日志
redis-cli -a your_secure_password_here slowlog get 10

7. Redis故障排除

问题1Redis服务无法启动

# 查看Redis日志
sudo journalctl -u redis-server -f

# 检查配置文件语法
sudo redis-server /etc/redis/redis.conf --test

# 检查端口占用
sudo netstat -tlnp | grep 6379

问题2连接被拒绝

# 检查防火墙设置
sudo ufw status
sudo ufw allow 6379/tcp

# 检查Redis绑定地址
sudo grep "^bind" /etc/redis/redis.conf

# 检查Redis是否在监听
sudo ss -tlnp | grep 6379

问题3内存不足

# 查看内存使用情况
redis-cli -a your_secure_password_here info memory

# 清理过期数据
redis-cli -a your_secure_password_here memory purge

# 调整内存策略
# 编辑 /etc/redis/redis.conf 调整 maxmemory 和 maxmemory-policy

8. 生产环境优化建议

  1. 使用独立Redis实例为Celery专门配置一个Redis实例
  2. 配置监控告警使用Prometheus + Grafana监控Redis性能
  3. 定期备份设置定时任务备份Redis数据
  4. 性能调优:根据实际使用情况调整内存和连接数配置
  5. 高可用方案考虑使用Redis Sentinel或Redis Cluster

9. Redis部署常见问题解答FAQ

Q1: Redis是必须的吗可以用其他消息队列替代吗

A: 是的Redis是必须的。家庭日报系统使用Celery进行异步任务处理而Celery默认使用Redis作为消息代理。虽然可以使用RabbitMQ、Amazon SQS等其他消息队列但需要修改Celery配置和代码。Redis是最简单、性能最好的选择。

Q2: Redis应该安装在哪台服务器上

A: 建议的部署方案:

  1. 小型部署Redis和Django应用安装在同一台服务器上推荐初学者
  2. 中型部署Redis安装在与Django应用不同的服务器上但在同一内网
  3. 生产部署使用Redis集群或云Redis服务如AWS ElastiCache、Azure Cache for Redis

Q3: Redis需要多少内存

A: 内存需求取决于使用情况:

  • 最小配置: 256MB适合小型家庭使用
  • 推荐配置: 1GB适合常规使用有增长空间
  • 生产配置: 2GB+(适合多用户或高频任务)

Q4: 如何设置Redis密码

A: 在 /etc/redis/redis.conf 中设置:

requirepass your_strong_password_here

然后在Django的 settings.py 中更新:

CELERY_BROKER_URL = 'redis://:your_strong_password_here@localhost:6379/0'

Q5: Redis数据会丢失吗

A: Redis默认将数据存储在内存中重启服务会丢失数据。但可以通过配置持久化来避免

# 在redis.conf中启用持久化
save 900 1      # 900秒内至少有1个键被修改
save 300 10     # 300秒内至少有10个键被修改  
save 60 10000   # 60秒内至少有10000个键被修改

Q6: 如何监控Redis性能

A: 使用以下命令监控:

# 实时监控
redis-cli -a your_password monitor

# 查看统计信息
redis-cli -a your_password info

# 查看慢查询
redis-cli -a your_password slowlog get 10

Q7: Celery任务堆积怎么办

A: 处理步骤:

  1. 增加worker数量celery -A diary_family worker --concurrency=4 -l info
  2. 优化任务代码,减少执行时间
  3. 使用优先级队列
  4. 监控Redis内存使用防止内存不足

Q8: 如何备份Redis数据

A: 备份方法:

# 手动备份
sudo cp /var/lib/redis/dump.rdb /backup/redis/dump.rdb.$(date +%Y%m%d)

# 自动备份添加到crontab
0 2 * * * sudo cp /var/lib/redis/dump.rdb /backup/redis/dump.rdb.$(date +\%Y\%m\%d)

Q9: Redis连接数过多怎么办

A: 解决方法:

  1. 增加最大连接数在redis.conf中
    maxclients 10000
    
  2. 优化Celery连接池
  3. 检查是否有连接泄漏

Q10: 如何验证Redis部署是否成功

A: 使用项目提供的测试脚本:

# 运行完整测试
python test_redis_celery.py

# 预期输出:所有测试通过,显示绿色成功信息

Q11: 生产环境Redis安全注意事项

A: 安全配置清单:

  • 设置强密码
  • 绑定到127.0.0.1或内网IP
  • 禁用危险命令FLUSHALL, FLUSHDB, CONFIG
  • 启用防火墙,只允许必要端口
  • 定期更新Redis版本
  • 配置日志监控

Q12: Redis性能调优参数有哪些

A: 关键调优参数:

# 内存管理
maxmemory 1gb
maxmemory-policy allkeys-lru

# 持久化优化
save 900 1
save 300 10
save 60 10000

# 网络优化
tcp-keepalive 60
timeout 300

常规代码更新流程

当需要更新代码时,可以使用以下命令:

# 退出虚拟环境
deactivate

# 切换到项目目录
cd /var/www/diary-family

# 1. 拉取远程最新代码(只获取,不合并)
git fetch origin

# 2. 硬重置本地分支到远程分支的最新版本(会覆盖所有本地未提交修改)
# 注意:将 main 替换为你的分支名(如 master、dev 等)
git reset --hard origin/main

# 3. 激活虚拟环境
source venv/bin/activate

# 4. 安装新依赖(如果有)
pip install -r requirements.txt

# 5. 收集静态文件(如果有静态文件更新)
python manage.py collectstatic --noinput

# 6. 重启服务
sudo supervisorctl restart all
sudo systemctl restart nginx

系统配置

在系统配置页面可以设置:

  • SMTP服务器信息
  • 邮件发送时间
  • 收件人邮箱

Celery 定时发送邮件任务配置

1. 邮件配置设置

在系统配置页面设置完邮件信息后,还需要在 Django 项目的 settings.py 中添加基础邮件配置:

# 邮件基础配置
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_PORT = 587  # 或根据你的 SMTP 服务器设置
EMAIL_USE_TLS = True  # 或根据你的 SMTP 服务器设置

2. 启动 Celery Worker 和 Beat

开发环境

# 启动 Celery Worker
celery -A diary_family worker -l info

# 启动 Celery Beat用于定时任务调度
celery -A diary_family beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler

生产环境

建议使用 supervisor 管理 Celery 进程。创建两个 supervisor 配置文件:

  1. celery_worker.conf

    [program:celery_worker]
    command=/path/to/venv/bin/celery -A diary_family worker -l info
    directory=/path/to/diary-family
    user=www-data
    group=www-data
    autostart=true
    autorestart=true
    stdout_logfile=/var/log/celery/worker.log
    stderr_logfile=/var/log/celery/worker_error.log
    
  2. celery_beat.conf

    [program:celery_beat]
    command=/path/to/venv/bin/celery -A diary_family beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler
    directory=/path/to/diary-family
    user=www-data
    group=www-data
    autostart=true
    autorestart=true
    stdout_logfile=/var/log/celery/beat.log
    stderr_logfile=/var/log/celery/beat_error.log
    

启动 supervisor 服务:

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl start celery_worker
sudo supervisorctl start celery_beat

3. 配置定时任务

系统使用 django_celery_beat 进行定时任务管理,支持两种方式配置:

方式一:通过 Django 管理后台(推荐)

  1. 登录 Django 管理后台(/houtai
  2. 找到 Periodic tasks(周期性任务)
  3. 点击 Add 按钮添加新任务
  4. 配置任务:
    • Name: 任务名称(如:每日报告发送)
    • Task (registered): 选择 core.tasks.send_daily_report
    • Interval: 设置执行间隔(如:每天)
    • Enabled: 勾选启用
  5. 点击 Save 保存

方式二:通过代码配置

core/tasks.py 中添加定时任务配置:

from celery import shared_task
from django_celery_beat.models import PeriodicTask, IntervalSchedule

# 创建或更新定时任务
def setup_daily_report_task():
    # 创建每天执行的间隔
    schedule, created = IntervalSchedule.objects.get_or_create(
        every=1,
        period=IntervalSchedule.DAYS,
    )
    
    # 创建或更新定时任务
    task, created = PeriodicTask.objects.update_or_create(
        name='Daily Report Task',
        defaults={
            'interval': schedule,
            'task': 'core.tasks.send_daily_report',
        },
    )
    return task

然后在 Django 启动时调用此函数(如在 core/apps.py 中)。

4. 验证任务执行

  • 查看 Celery 日志:tail -f /var/log/celery/worker.log
  • 检查邮件是否正常发送
  • 在 Django 管理后台查看任务执行记录

5. 日志文件不存在问题解决方法

如果在生产服务器上执行 tail -f /var/log/celery/worker.log 时提示 No such file or directory,请按照以下步骤解决:

步骤1检查日志目录是否存在

# 检查日志目录是否存在
ls -la /var/log/celery/

# 如果目录不存在,创建目录
sudo mkdir -p /var/log/celery/

# 设置正确的权限(确保 Celery 进程用户有读写权限)
sudo chown -R www-data:www-data /var/log/celery/
sudo chmod -R 755 /var/log/celery/

步骤2检查 Supervisor 配置

确保 Supervisor 配置文件中指定的日志路径正确,并且 Celery 进程用户对该路径有读写权限。

步骤3重启 Supervisor 和 Celery

sudo supervisorctl reread
sudo supervisorctl update
sudo supervisorctl restart celery_worker celery_beat

5.1 日志文件查看指南

在生产环境中,有多种日志来源,了解每种日志的位置和查看方法非常重要:

5.1.1 Celery Worker 和 Beat 日志

这些日志由 Celery 进程产生,需要先创建日志目录:

# 创建日志目录
sudo mkdir -p /var/log/celery/

# 设置权限
sudo chown -R www-data:www-data /var/log/celery/
sudo chmod -R 755 /var/log/celery/

查看日志:

# 实时查看 Worker 日志
tail -f /var/log/celery/worker.log

# 实时查看 Beat 日志
tail -f /var/log/celery/beat.log

# 查看最近50行
tail -n 50 /var/log/celery/worker.log

# 搜索错误信息
grep -i error /var/log/celery/worker.log

# 搜索特定任务
grep -i "generate_daily_pdf_report" /var/log/celery/worker.log

5.1.2 测试脚本日志

运行测试脚本时,日志会同时输出到控制台和文件:

# 运行测试脚本(输出到控制台)
python test_redis_celery.py

# 查看测试日志文件
tail -f /var/log/celery/test_redis_celery.log

# 运行测试并保存到文件
python test_redis_celery.py 2>&1 | tee /var/log/celery/test_output.log

测试脚本日志内容示例:

2024-01-15 10:30:00 | INFO     | 开始测试Redis连接...
2024-01-15 10:30:01 | SUCCESS  | Redis连接测试通过
2024-01-15 10:30:02 | INFO     | 开始测试Celery与Redis集成...
2024-01-15 10:30:03 | SUCCESS  | Celery与Redis集成测试通过

5.1.3 Redis 日志

Redis 的日志通常在系统日志中:

# 查看 Redis 系统日志
sudo journalctl -u redis-server -f

# 查看 Redis 错误日志
sudo tail -f /var/log/redis/redis-server.log

# 查看所有 Redis 相关日志
sudo grep -i redis /var/log/syslog

5.1.4 Django 应用日志

# 查看 Django 应用日志
tail -f /path/to/diary-family/logs/app.log

# 查看 Gunicorn 日志
sudo tail -f /var/log/gunicorn/access.log
sudo tail -f /var/log/gunicorn/error.log

5.1.5 Nginx 日志

# 查看访问日志
sudo tail -f /var/log/nginx/access.log

# 查看错误日志
sudo tail -f /var/log/nginx/error.log

5.1.6 综合日志查看脚本

创建一个综合日志查看脚本:

#!/bin/bash
# save as: /usr/local/bin/view-all-logs

echo "=== Celery Worker Log ==="
tail -n 20 /var/log/celery/worker.log

echo -e "\n=== Celery Beat Log ==="
tail -n 20 /var/log/celery/beat.log

echo -e "\n=== Redis Server Log ==="
sudo tail -n 20 /var/log/redis/redis-server.log

echo -e "\n=== Nginx Error Log ==="
sudo tail -n 20 /var/log/nginx/error.log

使用方法:

# 给脚本添加执行权限
sudo chmod +x /usr/local/bin/view-all-logs

# 运行脚本
view-all-logs

5.1.7 日志轮转配置

为防止日志文件过大,配置日志轮转:

创建 /etc/logrotate.d/celery-app

/var/log/celery/*.log {
    daily
    missingok
    rotate 14
    compress
    delaycompress
    notifempty
    create 0640 www-data www-data
    sharedscripts
    postrotate
        supervisorctl restart celery_worker celery_beat > /dev/null 2>&1 || true
    endscript
}

启用配置:

sudo logrotate -f /etc/logrotate.d/celery-app

5.1.8 日志查看常见问题

问题1日志文件权限被拒绝

# 检查权限
ls -la /var/log/celery/

# 如果权限不对,重新设置
sudo chown -R www-data:www-data /var/log/celery/
sudo chmod -R 755 /var/log/celery/

问题2日志文件不存在

# 检查目录是否存在
ls -la /var/log/ | grep celery

# 如果不存在,创建目录
sudo mkdir -p /var/log/celery/
sudo chown www-data:www-data /var/log/celery/

问题3日志不更新

# 检查进程是否运行
ps aux | grep celery

# 检查文件是否被锁定
sudo lsof /var/log/celery/worker.log

# 检查磁盘空间
df -h /var/log/

问题4如何清理旧日志

# 删除7天前的日志
find /var/log/celery/ -name "*.log.*.gz" -mtime +7 -delete

# 清空当前日志文件(谨慎使用)
sudo truncate -s 0 /var/log/celery/worker.log

6. 试运行周期任务

当设置一个周期任务后,您可以通过以下方式试运行任务,而不需要等待到指定的时间:

方式1通过 Django 管理后台

  1. 登录 Django 管理后台(/houtai
  2. 找到 Periodic tasks(周期性任务)
  3. 选择您创建的任务
  4. 点击页面底部的 Run Task 按钮立即执行任务

方式2通过命令行

# 直接调用任务函数(同步执行)
python manage.py shell -c "from core.tasks import generate_daily_pdf_report; generate_daily_pdf_report()"

# 或者使用 Celery 命令行工具
celery -A diary_family call core.tasks.generate_daily_pdf_report

方式3使用测试脚本

项目提供了多个测试脚本,用于验证不同功能:

  1. Celery任务测试

    # 测试Celery任务执行
    python test_celery.py
    
  2. Redis和Celery集成测试(生产环境推荐):

    # 测试Redis连接、Celery集成和性能
    python test_redis_celery.py
    
  3. Redis连接测试(快速验证):

    # 仅测试Redis连接
    python -c "import redis; r = redis.Redis(host='localhost', port=6379); print('Redis连接成功' if r.ping() else '连接失败')"
    

7. 常见错误和解决方法

错误1日志文件不存在

错误信息tail: cannot open '/var/log/celery/worker.log' for reading: No such file or directory

解决方法

  • 按照步骤5中的说明创建日志目录并设置正确权限
  • 检查 Supervisor 配置中的日志路径是否正确
  • 重启 Supervisor 和 Celery 服务

错误2Celery 无法连接到 Redis

错误信息redis.exceptions.ConnectionError: Error 111 connecting to localhost:6379. Connection refused.

解决方法

  1. 检查Redis服务状态

    sudo systemctl status redis-server
    
  2. 如果Redis未运行启动服务

    sudo systemctl start redis-server
    sudo systemctl enable redis-server
    
  3. 检查Redis配置

    • 确保Redis配置文件 /etc/redis/redis.confbind 设置为 127.0.0.1
    • 检查是否有防火墙阻止连接:sudo ufw status
    • 检查端口是否被占用:sudo netstat -tlnp | grep 6379
  4. 测试Redis连接

    # 测试基本连接
    redis-cli ping
    
    # 如果设置了密码,使用密码连接
    redis-cli -a your_password ping
    
  5. 检查Celery配置

    • 确保 settings.py 中的 CELERY_BROKER_URLCELERY_RESULT_BACKEND 配置正确
    • 如果Redis有密码URL格式应为redis://:password@localhost:6379/0
  6. 详细排查

    • 查看Redis日志sudo journalctl -u redis-server -f
    • 查看Celery日志tail -f /var/log/celery/worker.log
    • 参考 Redis服务器部署 章节进行完整配置

注意:如果这是新部署的环境,请确保已按照 Redis服务器部署 章节完整安装和配置Redis。

错误3任务执行失败

错误信息Task core.tasks.generate_daily_pdf_report[xxx] raised unexpected: Exception(...)

解决方法

  • 查看详细日志:tail -f /var/log/celery/worker.log
  • 检查任务代码中的错误
  • 确保所有依赖库都已正确安装
  • 检查相关服务如数据库、Redis是否正常运行

错误4PDF 生成失败

错误信息WeasyPrint库不可用无法生成PDF报告

解决方法

  • 安装 WeasyPrint 库:pip install weasyprint
  • 对于 Ubuntu 系统,可能需要安装系统依赖:
    sudo apt-get install -y libpango-1.0-0 libpangoft2-1.0-0
    

8. 常见问题排查

  1. 任务不执行

    • 检查 Celery worker 和 beat 是否正常运行
    • 检查 Redis 服务是否正常
    • 检查任务是否已启用
    • 检查系统时间是否正确
  2. 邮件发送失败

    • 检查 SMTP 服务器配置是否正确
    • 检查邮箱账号密码是否正确
    • 检查收件人邮箱格式是否正确
    • 查看 Celery 日志中的错误信息
  3. 任务执行延迟

    • 检查系统负载是否过高
    • 考虑增加 Celery worker 数量
    • 检查 Redis 性能

6. 生产环境优化建议

Redis相关优化

  1. 使用独立Redis实例为Celery专门配置一个Redis实例避免与其他应用共享
  2. Redis性能调优
    • 根据服务器内存调整 maxmemory 配置
    • 使用合适的内存淘汰策略(如 allkeys-lru
    • 启用持久化确保数据安全
  3. Redis监控
    • 配置Prometheus + Grafana监控Redis性能
    • 设置内存使用告警
    • 监控连接数和慢查询

Celery相关优化

  1. Worker配置
    • 配置合适的worker数量建议CPU核心数 × 2
    • 使用prefork或gevent模式根据任务类型选择
    • 设置合理的任务超时时间
  2. 任务管理
    • 定期清理Celery任务结果
    • 配置任务重试机制
    • 使用任务优先级队列
  3. 监控工具
    • 启用Celery监控工具如Flower
    • 配置任务执行统计
    • 设置任务失败告警

系统级优化:

  1. 资源隔离为Celery worker和Redis分配独立的系统资源
  2. 日志管理配置集中式日志收集如ELK Stack
  3. 备份策略定期备份Redis数据和任务结果
  4. 高可用方案考虑使用Redis Sentinel或Redis Cluster实现高可用

定时生成PDF文件配置

除了定时发送邮件外系统还支持单独定时生成PDF文件便于在服务器上保存历史报告。

1. 配置定时生成PDF任务

方式一:通过 Django 管理后台(推荐)

  1. 登录 Django 管理后台(/houtai
  2. 找到 Periodic tasks(周期性任务)
  3. 点击 Add 按钮添加新任务
  4. 配置任务:
    • Name: 任务名称每日PDF报告生成
    • Task (registered): 选择 core.tasks.generate_daily_pdf_report
    • Interval: 设置执行间隔(如:每天)
    • Enabled: 勾选启用
  5. 点击 Save 保存

方式二:通过代码配置

core/tasks.py 中添加定时任务配置:

from celery import shared_task
from django_celery_beat.models import PeriodicTask, IntervalSchedule

# 创建或更新PDF生成定时任务
def setup_daily_pdf_task():
    # 创建每天执行的间隔
    schedule, created = IntervalSchedule.objects.get_or_create(
        every=1,
        period=IntervalSchedule.DAYS,
    )
    
    # 创建或更新定时任务
    task, created = PeriodicTask.objects.update_or_create(
        name='Daily PDF Generation Task',
        defaults={
            'interval': schedule,
            'task': 'core.tasks.generate_daily_pdf_report',
        },
    )
    return task

然后在 Django 启动时调用此函数(如在 core/apps.py 中)。

2. PDF文件存储位置

生成的PDF文件默认存储在项目的 reports 目录下,命名格式为 report_YYYY-MM-DD.pdf

可以在 settings.py 中修改存储位置:

# Reports files configuration
REPORTS_URL = '/reports/'
REPORTS_ROOT = BASE_DIR / 'reports'  # 可以修改为其他路径

3. 验证PDF生成任务

  • 查看 Celery 日志:tail -f /var/log/celery/worker.log
  • 检查PDF文件是否生成ls -la /path/to/diary-family/reports/
  • 在 Django 管理后台查看任务执行记录

4. 常见问题排查

  1. PDF生成失败

    • 检查 WeasyPrint 库是否正确安装:pip list | grep weasyprint
    • 检查系统字体是否完整PDF生成需要系统字体支持
    • 查看 Celery 日志中的错误信息
  2. 任务执行但没有生成文件

    • 检查 REPORTS_ROOT 目录权限:确保 Celery 进程有写入权限
    • 检查磁盘空间是否充足
    • 查看 Celery 日志中的详细信息
  3. PDF内容不完整

    • 检查模板文件 core/templates/core/report_pdf.html 是否完整
    • 确保所有依赖的 CSS 和图像资源都能正常访问

邮件功能测试

项目提供了两个专门的测试脚本,用于验证邮件发送功能是否正常工作:

1. 基础邮件测试test_email.py

用于测试直接邮件发送功能验证SMTP配置是否正确。

测试内容

  • 邮件配置验证
  • SMTP连接测试
  • 发送简单文本邮件
  • 发送HTML邮件带附件
  • 邮件发送性能测试

运行方式

# 运行基础邮件测试
python test_email.py

测试结果说明

  • 所有测试通过:邮件系统配置正确,可以正常工作
  • 3项以上通过邮件系统基本可用部分功能可能需要优化
  • 少于3项通过邮件系统存在严重问题需要检查配置

2. Celery异步邮件测试test_celery_email.py

用于测试通过Celery异步发送邮件的功能验证整个异步任务链是否正常。

测试内容

  • Celery邮件配置验证
  • Celery Worker状态检查
  • Celery异步邮件任务执行
  • 同步发送测试邮件(用于对比)

运行方式

# 运行Celery异步邮件测试
python test_celery_email.py

测试结果说明

  • 所有测试通过Celery邮件功能正常
  • 2项以上通过Celery邮件功能基本可用
  • 少于2项通过存在严重问题需要检查配置

3. 常见问题排查

测试失败时的检查步骤

  1. 检查SMTP配置

    # 查看Django邮件配置
    python -c "import os; os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'diary_family.settings'); import django; django.setup(); from django.conf import settings; print('EMAIL_HOST:', getattr(settings, 'EMAIL_HOST', None)); print('EMAIL_PORT:', getattr(settings, 'EMAIL_PORT', None)); print('EMAIL_HOST_USER:', getattr(settings, 'EMAIL_HOST_USER', None))"
    
  2. 检查Redis服务

    sudo systemctl status redis-server
    redis-cli ping
    
  3. 检查Celery Worker状态

    # 查看Celery Worker状态
    celery -A diary_family status
    
    # 如果Worker未运行启动它
    celery -A diary_family worker -l info
    
  4. 查看日志文件

    # 查看邮件测试日志
    tail -f /var/log/celery/test_email.log
    tail -f /var/log/celery/test_celery_email.log
    
    # 查看Celery日志
    tail -f /var/log/celery/worker.log
    tail -f /var/log/celery/beat.log
    
  5. 验证网络连通性

    # 测试SMTP服务器连通性
    telnet smtp.example.com 587
    
    # 测试DNS解析
    nslookup smtp.example.com
    

常见错误及解决方案

错误信息 可能原因 解决方案
连接被拒绝 SMTP服务器地址/端口错误 检查SMTP配置确认服务器地址和端口
认证失败 用户名或密码错误 检查邮箱账号和密码确认是否开启了SMTP服务
Celery连接失败 Redis未运行或配置错误 检查Redis服务状态验证CELERY_BROKER_URL配置
任务超时 Worker未运行或任务执行时间过长 启动Celery Worker检查任务代码

Celery 监控(可选)

使用 Flower 监控 Celery 任务:

# 安装 Flower
pip install flower

# 启动 Flower
celery -A diary_family flower --port=5555

访问 http://your-server:5555 查看任务监控界面。

RPA/自动化脚本 CSRF保护问题解决方案

当使用RPA机器人流程自动化或自动化脚本调用系统API时可能会遇到Django的CSRF跨站请求伪造保护机制拦截的问题。

问题现象

  • 调用API返回 403 Forbidden 错误
  • 错误信息包含 CSRF verification failedForbidden (CSRF cookie not set.)
  • RPA工具无法正常提交数据到 /api/v1/summary/submit/

问题原因

Django默认启用CSRF保护中间件CsrfViewMiddleware所有POST请求都需要提供有效的CSRF令牌。但自动化脚本和RPA工具无法像浏览器一样获取和携带CSRF令牌。

解决方案

方案一为API视图添加CSRF豁免推荐

修改 core/views.py 文件为API提交接口添加 @csrf_exempt 装饰器:

from django.views.decorators.csrf import csrf_exempt

# 在 api_submit_summary 函数前添加装饰器
@csrf_exempt
def api_submit_summary(request):
    """API提交汇总记录 - 仅接受指定分类和发言人的记录"""
    # ... 原有代码保持不变 ...

操作步骤

  1. 打开 core/views.py 文件
  2. 确保文件顶部已导入 csrf_exempt
    from django.views.decorators.csrf import csrf_exempt
    
  3. api_submit_summary 函数定义前添加 @csrf_exempt 装饰器
  4. 保存文件并重启Gunicorn服务
    sudo supervisorctl restart diary-family
    # 或
    sudo systemctl restart gunicorn
    

方案二配置CSRF信任域名

如果不想完全禁用CSRF保护可以在 settings.py 中配置信任的域名:

# 在 settings.py 中添加
CSRF_TRUSTED_ORIGINS = [
    'https://your-domain.com',
    'https://*.your-domain.com',
]

# 如果使用IP访问添加IP地址
CSRF_TRUSTED_ORIGINS = [
    'http://192.168.1.100',
    'http://localhost',
]

方案三为特定URL路径禁用CSRF

core/views.py 中创建一个通用的API装饰器

from django.views.decorators.csrf import csrf_exempt
from functools import wraps

def api_exempt(view_func):
    """
    API接口CSRF豁免装饰器
    用于标记不需要CSRF保护的API接口
    """
    @wraps(view_func)
    @csrf_exempt
    def wrapped_view(request, *args, **kwargs):
        # 可以在这里添加API认证逻辑
        return view_func(request, *args, **kwargs)
    return wrapped_view

# 使用方式
@api_exempt
def api_submit_summary(request):
    # ... 原有代码 ...

安全建议

  1. 仅对必要的API接口禁用CSRF保护,不要对整个视图或应用禁用
  2. 添加API认证机制如API Key、Token认证替代CSRF保护
  3. 限制API访问来源IP在Nginx或防火墙层面进行限制
  4. 使用HTTPS协议确保数据传输安全
  5. 记录API访问日志,便于审计和排查问题

验证修复

修改配置后使用以下命令验证API是否可正常访问

# 测试API接口
curl -X POST http://your-server/api/v1/summary/submit/ \
  -d "content=测试内容"

# 预期返回
{"success": true, "message": "提交成功", "id": 123}

常见问题

Q1: 添加 @csrf_exempt 后是否安全?

A: 对于内部API和自动化脚本调用的接口添加 @csrf_exempt 是安全的,因为:

  • API接口通常需要其他形式的认证如API Key
  • 自动化脚本运行在受控环境中
  • 可以结合IP白名单、请求频率限制等安全措施

Q2: 如何在RPA工具中处理CSRF

A: 推荐在服务器端禁用CSRF保护方案一而不是在RPA工具中处理CSRF令牌。这样可以简化RPA脚本的复杂度。

Q3: 修改后需要重启服务吗?

A: 是的Python代码修改后需要重启Gunicorn或uWSGI服务才能生效

sudo supervisorctl restart all
# 或
sudo systemctl restart gunicorn

API接口文档

系统提供RESTful API接口用于外部客户端提交汇总记录。

1. 汇总记录提交API

用于外部客户端(如监控脚本、自动化任务)向系统提交汇总记录。

请求信息

  • URL: /api/v1/summary/submit/
  • 方法: POST
  • Content-Type: application/x-www-form-urlencodedmultipart/form-data

请求参数

参数名 类型 必填 说明
content string 汇总记录内容,最大长度不限

响应格式

成功响应 (HTTP 200):

{
    "success": true,
    "message": "提交成功",
    "id": 123
}

失败响应 (HTTP 400/500):

{
    "success": false,
    "message": "错误信息描述"
}

调用示例

# 使用 curl 提交汇总记录
curl -X POST http://your-server/api/v1/summary/submit/ \
  -d "content=这是自动提交的汇总内容"

# Python requests 调用示例
import requests

url = "http://your-server/api/v1/summary/submit/"
data = {
    "content": "监控报告系统运行正常CPU使用率15%内存使用率42%"
}

response = requests.post(url, data=data)
result = response.json()
print(result)

客户端自动提交示例

创建一个Python脚本用于自动提交系统监控数据

#!/usr/bin/env python3
# submit_summary.py

import socket
import psutil
import requests
from datetime import datetime

def get_system_info():
    """获取系统基本信息"""
    cpu_percent = psutil.cpu_percent(interval=1)
    memory = psutil.virtual_memory()
    disk = psutil.disk_usage('/')
    return {
        'cpu': cpu_percent,
        'memory': memory.percent,
        'disk': disk.percent
    }

def submit_summary(content):
    """提交汇总记录到家庭日报系统"""
    url = "http://your-server/api/v1/summary/submit/"
    try:
        response = requests.post(url, data={'content': content}, timeout=10)
        result = response.json()
        if result['success']:
            print(f"提交成功记录ID: {result['id']}")
        else:
            print(f"提交失败: {result['message']}")
    except Exception as e:
        print(f"请求异常: {str(e)}")

if __name__ == "__main__":
    info = get_system_info()
    timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    content = f"[系统监控 {timestamp}] CPU使用率: {info['cpu']}%, 内存使用率: {info['memory']}%, 磁盘使用率: {info['disk']}%"
    submit_summary(content)

注意事项

  1. 数据验证API仅接受以下条件的记录

    • 分类必须为"定期"
    • 发言人必须为"机器人"
    • 内容不能为空
  2. 来源自动生成系统会自动获取客户端的主机名和IP地址填充到source字段。

  3. 日期自动设置:记录日期自动设置为提交时的日期。

  4. 错误处理如果分类或发言人不存在API会返回错误信息。

2. 初始化必需数据

在使用API提交功能前需要确保数据库中存在以下数据

方法一Django Shell初始化

python manage.py shell -c "
from core.models import SummaryCategory, FamilyMember

# 创建'定期'分类(如果不存在)
category, created = SummaryCategory.objects.get_or_create(name='定期')
if created:
    print('创建分类: 定期')
else:
    print('分类已存在: 定期')

# 创建'机器人'发言人(如果不存在)
speaker, created = FamilyMember.objects.get_or_create(name='机器人')
if created:
    print('创建发言人: 机器人')
else:
    print('发言人已存在: 机器人')

print('初始化完成')
"

方法二Django Admin后台创建

  1. 登录后台管理:/houtai
  2. 汇总分类 中添加名为"定期"的分类
  3. 家庭成员 中添加名为"机器人"的成员

3. 常见问题排查

问题1提交返回"分类 '定期' 不存在"

解决方法:在数据库中创建该分类(见上方初始化方法)

问题2提交返回"发言人 '机器人' 不存在"

解决方法:在数据库中创建该发言人(见上方初始化方法)

问题3提交返回"内容不能为空"

解决方法:确保请求中包含 content 参数且不为空

问题4返回HTTP 405错误

解决方法确认使用的是POST方法不是GET方法

Fail2ban 登录保护配置

为了防止暴力破解登录密码,系统集成了 Fail2ban 自动封禁功能。当用户在短时间内多次登录失败时,其 IP 地址将被自动封禁。

工作原理

  1. 日志记录:登录失败时,系统会记录包含 IP 地址的警告日志到 syslog 和 logs/auth.log
  2. Fail2ban 监控Fail2ban 实时监控日志文件,检测登录失败事件
  3. 自动封禁:当同一 IP 在指定时间内失败次数超过阈值时,自动封禁该 IP

安装 Fail2ban

在 Ubuntu 服务器上安装 Fail2ban

# 更新包管理器
sudo apt update

# 安装 Fail2ban
sudo apt install fail2ban -y

# 启动 Fail2ban 服务
sudo systemctl start fail2ban

# 设置开机自启
sudo systemctl enable fail2ban

# 检查服务状态
sudo systemctl status fail2ban

配置 Fail2ban

1. 复制过滤器配置

# 创建过滤器目录(如果不存在)
sudo mkdir -p /etc/fail2ban/filter.d

# 复制过滤器配置
sudo cp /var/www/diary-family/deploy/fail2ban/filter.d/diary-family.conf /etc/fail2ban/filter.d/

# 验证过滤器配置
sudo fail2ban-client -t

2. 复制监狱配置

# 创建监狱配置目录(如果不存在)
sudo mkdir -p /etc/fail2ban/jail.d

# 复制监狱配置
sudo cp /var/www/diary-family/deploy/fail2ban/jail.d/diary-family.conf /etc/fail2ban/jail.d/

# 编辑配置(根据实际需求修改)
sudo nano /etc/fail2ban/jail.d/diary-family.conf

3. 关键配置参数说明

参数 默认值 说明
maxretry 5 触发封禁前的最大失败次数
bantime 3600 封禁时间默认1小时
findtime 600 检测时间窗口默认10分钟
ignoreip 127.0.0.1 白名单IP不会被封禁

4. 重启 Fail2ban 服务

# 重新加载配置
sudo systemctl restart fail2ban

# 或者使用 fail2ban-client
sudo fail2ban-client reload

验证配置

1. 检查 Fail2ban 状态

# 查看整体状态
sudo fail2ban-client status

# 查看 diary-family 监狱状态
sudo fail2ban-client status diary-family

# 查看被封禁的IP列表
sudo fail2ban-client status diary-family | grep "Banned IP list"

2. 测试登录失败检测

# 手动测试过滤器(使用最近的日志)
sudo fail2ban-regex /var/log/syslog /etc/fail2ban/filter.d/diary-family.conf

# 或者测试 auth.log
sudo fail2ban-regex /var/www/diary-family/logs/auth.log /etc/fail2ban/filter.d/diary-family.conf

3. 查看日志

# 查看 Fail2ban 日志
sudo tail -f /var/log/fail2ban.log

# 查看系统日志中的认证失败
sudo grep "Authentication failure" /var/log/syslog

# 查看 Django 认证日志
tail -f /var/www/diary-family/logs/auth.log

手动管理封禁

解封 IP 地址

# 手动解封某个 IP
sudo fail2ban-client set diary-family unbanip 192.168.1.100

# 解封所有 IP
sudo fail2ban-client set diary-family unbanip --all

封禁 IP 地址

# 手动封禁某个 IP
sudo fail2ban-client set diary-family banip 192.168.1.100

高级配置

使用 UFW 作为防火墙后端

如果使用 UFW 防火墙,修改配置:

# 编辑监狱配置
sudo nano /etc/fail2ban/jail.d/diary-family.conf

# 修改 banaction
banaction = ufw

# 重启服务
sudo systemctl restart fail2ban

配置邮件通知

启用邮件通知功能:

# 编辑监狱配置
sudo nano /etc/fail2ban/jail.d/diary-family.conf

# 添加邮件配置
destemail = admin@example.com
sender = fail2ban@example.com
mta = sendmail
action = %(action_mwl)s

# 重启服务
sudo systemctl restart fail2ban

调整封禁策略

编辑 /etc/fail2ban/jail.d/diary-family.conf

# 更严格的策略3次失败封禁24小时
maxretry = 3
bantime = 86400
findtime = 300

# 或者更宽松的策略10次失败封禁30分钟
maxretry = 10
bantime = 1800
findtime = 900

故障排除

问题1Fail2ban 无法启动

# 检查配置文件语法
sudo fail2ban-client -t

# 查看详细错误信息
sudo journalctl -u fail2ban -f

# 检查日志文件权限
ls -la /var/log/syslog
ls -la /var/www/diary-family/logs/auth.log

问题2无法检测到登录失败

# 检查日志格式是否匹配
sudo fail2ban-regex /var/log/syslog /etc/fail2ban/filter.d/diary-family.conf

# 手动检查日志内容
grep "Authentication failure" /var/log/syslog
grep "Authentication failure" /var/www/diary-family/logs/auth.log

# 检查 Django 是否正确记录日志
tail -f /var/www/diary-family/logs/auth.log

问题3IP 未被封禁

# 检查 iptables 规则
sudo iptables -L -n | grep fail2ban

# 检查封禁状态
sudo fail2ban-client status diary-family

# 检查日志中是否有封禁动作
sudo grep "Ban" /var/log/fail2ban.log

问题4syslog 无法写入

如果使用 syslog 出现权限问题,可以只使用文件日志:

# 编辑监狱配置,只监控 auth.log
sudo nano /etc/fail2ban/jail.d/diary-family.conf

# 修改 logpath
logpath = /var/www/diary-family/logs/auth.log

# 重启服务
sudo systemctl restart fail2ban

安全建议

  1. 合理设置阈值:根据实际需求调整 maxretryfindtime,避免误封正常用户
  2. 配置白名单:将办公网络、家庭网络等添加到 ignoreip
  3. 定期检查日志:定期查看 /var/log/fail2ban.log 了解封禁情况
  4. 设置永久封禁:对于频繁攻击的 IP可以手动永久封禁或设置很长的 bantime
  5. 监控异常:结合邮件通知,及时了解安全事件

与 Nginx 集成(可选)

如果使用 Nginx 作为反向代理,可以额外配置 Nginx 日志监控:

# 创建 Nginx 过滤器
sudo tee /etc/fail2ban/filter.d/nginx-diary-family.conf << 'EOF'
[Definition]
failregex = ^<HOST> .* "POST /login/ HTTP/.*" (401|403|500)
            ^<HOST> .* "POST /login/ HTTP/.*" 200 .* "Invalid login"
ignoreregex =
EOF

# 添加到监狱配置
sudo tee -a /etc/fail2ban/jail.d/diary-family.conf << 'EOF'

[nginx-diary-family]
enabled = true
filter = nginx-diary-family
logpath = /var/log/nginx/access.log
maxretry = 5
bantime = 3600
findtime = 600
EOF

# 重启服务
sudo systemctl restart fail2ban

注意事项

  1. 定期备份数据库
  2. 生产环境建议使用PostgreSQL或MySQL数据库
  3. 定期清理过期数据
  4. 保持依赖包更新
  5. 定期运行邮件测试脚本,确保邮件功能正常
  6. Fail2ban 配置:生产环境务必配置 Fail2ban 防止暴力破解
  7. 白名单设置:配置 ignoreip 避免误封自己的 IP

许可证

MIT License

Description
家庭的日常报告,包括阅读,体悟,运动,计划等等内容。
Readme 463 KiB
Languages
Python 56.4%
HTML 43.6%