PostgreSQL日志达log_rotation_size限制未轮转,保留文件名格式如何解决
问题根因
该问题确实和log_filename的配置直接相关,PostgreSQL 内置日志轮转的规则如下:
当触发轮转条件时,会首先生成新的日志文件名,若新文件名和已存在的文件重名:
- 如果轮转是时间触发(达到
log_rotation_age设置的时长,比如跨天),且开启了log_truncate_on_rotation = on,会清空原有同名文件写入 - 如果轮转是大小触发(达到
log_rotation_size阈值),即使开启了log_truncate_on_rotation,也不会清空或新建文件,只会继续往原有同名文件追加,这就是日志达到100MB后仍继续写入同一文件的原因。
可行解决方案
你需要保留postgresql-%Y-%m-%d.log格式、重启后写入当天同个文件的需求,无法仅通过PostgreSQL内置配置实现,需要配合外部脚本处理,不需要常驻后台服务,用系统自带的定时任务即可,开销极低。
实现逻辑
定期检查当前正在写入的日期格式日志的大小,达到100MB阈值时,将旧日志重命名为带序号的归档格式,之后触发PostgreSQL日志重载,PostgreSQL会自动生成新的postgresql-%Y-%m-%d.log文件写入。
操作步骤
- 保留你现有所有PostgreSQL日志配置不变
- 编写如下检查脚本(替换对应路径为你实际的PostgreSQL路径):
#!/bin/bash # 替换为你的日志目录路径 LOG_DIR="/var/lib/postgresql/13/main/log" # 100MB对应的字节数 MAX_SIZE=104857600 CURRENT_LOG_NAME=$(date +"postgresql-%Y-%m-%d.log") CURRENT_LOG_PATH="${LOG_DIR}/${CURRENT_LOG_NAME}" if [ -f "${CURRENT_LOG_PATH}" ] && [ $(stat -c%s "${CURRENT_LOG_PATH}") -ge ${MAX_SIZE} ]; then # 计算当前日期的归档日志最大序号 MAX_SEQ=$(ls "${LOG_DIR}/"$(date +"postgresql-%Y-%m-%d")*.log 2>/dev/null | grep -E '\.[0-9]+\.log$' | awk -F '.' '{print $(NF-1)}' | sort -n | tail -n 1) NEW_SEQ=$((MAX_SEQ + 1)) [ -z "${MAX_SEQ}" ] && NEW_SEQ=1 # 重命名归档旧日志 mv "${CURRENT_LOG_PATH}" "${LOG_DIR}/$(date +"postgresql-%Y-%m-%d").${NEW_SEQ}.log" # 触发PostgreSQL日志重载,以下两种方式二选一即可 # 方式1:用pg_ctl命令,注意替换数据目录路径 su - postgres -c "pg_ctl reload -D /var/lib/postgresql/13/main" # 方式2:直接发送SIGUSR1信号,替换为你的postmaster.pid路径 # kill -SIGUSR1 $(cat /var/lib/postgresql/13/main/postmaster.pid | head -n 1) fi
- 给脚本添加执行权限,之后在crontab中添加定时任务,每分钟执行一次即可:
# 编辑crontab crontab -e # 添加如下行,替换为你的脚本实际路径 * * * * * /path/to/your/log_rotate.sh >/dev/null 2>&1
该方案下,当前正在写入的日志永远是不带时分的日期格式,服务重启后也会自动写入当天的该文件,历史超过100MB的日志按序号归档不会丢失。
内容的提问来源于stack exchange,提问作者xxestter
相关产品推荐
相关产品推荐

