- 目标:在 Ubuntu 20.04 上实施 系统日志大小限制,防止 / 分区被日志写满。
- 涉及组件:
systemd-journald
(journalctl
)与rsyslog
+logrotate
。 - 关键位置:
/etc/systemd/journald.conf
、/etc/logrotate.d/rsyslog
、/var/log/
。 - 快速命令:
journalctl --disk-usage
、journalctl --vacuum-size=500M
、sudo logrotate -f /etc/logrotate.conf
。 - 推荐上限:Journal 总占用 ≤ 1G;
/var/log/syslog
单文件 ≤ 100M、保留 7 份、启用压缩。
核心原理:Ubuntu 20.04 的日志体系
Ubuntu 20.04 默认同时存在两条日志路径:
- systemd-journald:二进制日志(
journalctl
查看);可在内存(volatile)或磁盘(persistent)持久化。 - rsyslog + logrotate:传统文本日志(如
/var/log/syslog
、/var/log/kern.log
、/var/log/auth.log
)。
要实现“ubuntu20.04 系统日志大小限制”,需分别对 journald
与 logrotate
设定上限:前者控制 Journal 总体积与单文件大小,后者控制文本日志的轮转、压缩与保留份数。
方法一:限制 systemd-journald 体积(推荐)
1)启用持久化并设置总上限
如果希望限制落盘的 Journal 总体积,先确保持久化目录存在,然后编辑配置:
sudo mkdir -p /var/log/journal
sudo nano /etc/systemd/journald.conf
在 [Journal]
段添加或修改如下(示例值可按磁盘大小微调):
[Journal]
Storage=persistent
SystemMaxUse=1G
SystemKeepFree=500M
SystemMaxFileSize=200M
SystemMaxFiles=10
RuntimeMaxUse=200M
RuntimeKeepFree=50M
字段说明:
Storage=persistent
:将日志持久化到磁盘(/var/log/journal
)。SystemMaxUse
:Journal 持久化日志的总占用上限(例如 1G)。SystemKeepFree
:为系统磁盘至少预留的空间,防止被日志写爆(如 500M)。SystemMaxFileSize
:单个 Journal 文件最大大小(如 200M)。SystemMaxFiles
:最多保留的 Journal 文件个数。RuntimeMaxUse
/RuntimeKeepFree
:仅内存日志时的上限与预留(/run)。
保存后重启服务使之生效:
sudo systemctl restart systemd-journald
2)立刻“瘦身”到指定大小或时长
除了永久配置,还可用 journalctl
的清理命令即时收缩占用:
# 查看当前 Journal 占用
journalctl --disk-usage
# 将历史日志清理到不超过 500MB
sudo journalctl --vacuum-size=500M
# 或仅保留最近 14 天
sudo journalctl --vacuum-time=14d
3)常用数值建议(按服务器类型)
- 1~2 核 / 1–2GB RAM 小型实例:
SystemMaxUse=400M
、SystemMaxFileSize=100M
、SystemMaxFiles=6
。 - 通用 Web/应用服务器:
SystemMaxUse=1G
、SystemMaxFileSize=200M
、SystemMaxFiles=10
。 - 高并发/日志较多:
SystemMaxUse=2G
、SystemMaxFileSize=256M
、SystemMaxFiles=12
。
方法二:限制 /var/log 文件(logrotate 轮转)
logrotate
负责对 /var/log/*.log
做基于大小或时间的轮转、压缩与保留。Ubuntu 20.04 默认已启用,你只需在对应规则中声明“大小阈值 + 保留份数”。
1)修改 rsyslog 的轮转规则
编辑系统的 rsyslog 轮转文件:
sudo nano /etc/logrotate.d/rsyslog
(下一批将给出可直接粘贴的完整示例,覆盖 /var/log/syslog
、auth.log
、kern.log
等文件,并解释各指令如 size
、rotate
、compress
、copytruncate
的取舍。)
即用模板:拷贝即可的配置片段
为“ubuntu20.04 系统日志大小限制”准备的两段模板(journald 与 logrotate)会在下一批给到,你可直接覆盖并微调数值后应用。
验证与清理:立刻生效与占用回收
改完配置后,你应执行以下检查:
# 验证 journald 配置已加载
systemctl status systemd-journald
# 查看 Journal 占用并确认未超过上限
journalctl --disk-usage
# 强制执行一次轮转,验证 logrotate 规则
sudo logrotate -f /etc/logrotate.conf
# 观察 /var/log/ 占用
sudo du -sh /var/log/* | sort -h
常见问题 FAQ(节选)
Q1:设置了 SystemMaxUse 但占用仍偏大?
检查是否启用了持久化(Storage=persistent
)且目录 /var/log/journal
存在;重启 systemd-journald
后再用 --vacuum-size
收敛一次历史占用。
Q2:用 logrotate 后日志短暂停写会丢吗?
对写入频繁的文件建议加 copytruncate
,避免切换文件句柄时短暂停写;关键审计日志可选用 postrotate
里重载服务以确保句柄切换。
Q3:只想保留最近 N 天日志?
Journal 用 --vacuum-time=Nd
,logrotate 用 maxage N
或按天 daily
+ rotate
搭配。
即用模板一:/etc/systemd/journald.conf
(限制 Journal 体积)
将下列片段完整覆盖到 /etc/systemd/journald.conf
(保留注释亦可)。请按你的磁盘大小调整 SystemMaxUse
、SystemKeepFree
等数值。
[Journal]
# 将日志持久化到磁盘(目录:/var/log/journal)
Storage=persistent
# Journal 总体积上限,建议 400M~2G 之间
SystemMaxUse=1G
# 给根分区至少预留的剩余空间,避免被日志写满
SystemKeepFree=500M
# 单个 Journal 文件上限(达到后切新文件)
SystemMaxFileSize=200M
# 最多保留多少个 Journal 文件(与上限共同生效)
SystemMaxFiles=10
# 仅内存(/run)日志的上限与预留(Storage=volatile 时生效)
RuntimeMaxUse=200M
RuntimeKeepFree=50M
# 提示:Ubuntu 20.04 不建议使用太新的保留参数;以上即可控制体积
一键应用并重启:
sudo mkdir -p /var/log/journal
sudo tee /etc/systemd/journald.conf >/dev/null <<'EOF'
[Journal]
Storage=persistent
SystemMaxUse=1G
SystemKeepFree=500M
SystemMaxFileSize=200M
SystemMaxFiles=10
RuntimeMaxUse=200M
RuntimeKeepFree=50M
EOF
sudo systemctl restart systemd-journald
journalctl --disk-usage
即用模板二:/etc/logrotate.d/rsyslog
(限制 /var/log 文本日志)
该模板对常见日志按“达到指定大小即轮转 + 压缩 + 保留 N 份”处理。若你已有自定义规则,合并时注意去重。
/var/log/syslog
{
daily
size 100M
rotate 7
compress
delaycompress
missingok
notifempty
copytruncate
create 640 syslog adm
sharedscripts
postrotate
reload rsyslog >/dev/null 2>&1 || true
endscript
}
# 认证与安全相关日志
/var/log/auth.log /var/log/kern.log /var/log/faillog
{
weekly
size 50M
rotate 8
compress
delaycompress
missingok
notifempty
copytruncate
create 640 syslog adm
sharedscripts
postrotate
reload rsyslog >/dev/null 2>&1 || true
endscript
}
# APT/DPKG 相关日志
/var/log/apt/history.log /var/log/apt/term.log /var/log/dpkg.log
{
monthly
size 30M
rotate 6
compress
delaycompress
missingok
notifempty
copytruncate
create 640 root adm
}
# 防火墙/自动更新(若存在)
/var/log/ufw.log /var/log/unattended-upgrades/unattended-upgrades.log
{
weekly
size 50M
rotate 6
compress
delaycompress
missingok
notifempty
copytruncate
create 640 syslog adm
}
立即验证该规则:
# 强制执行一次轮转(用于验证)
sudo logrotate -f /etc/logrotate.conf
# 查看 /var/log 占用变化
sudo du -sh /var/log/* | sort -h
完整操作步骤(从检查到验证)
- 盘点当前占用:
df -h / sudo du -sh /var/log/* | sort -h journalctl --disk-usage
- 部署 Journald 限制:按上文“模板一”覆盖并
restart
。 - 部署 Logrotate 限制:按上文“模板二”覆盖。
- 即时回收历史占用(可选):
sudo journalctl --vacuum-size=500M # 将 Journal 收敛到 500MB sudo logrotate -f /etc/logrotate.conf # 立刻轮转文本日志
- 再次核验:
journalctl --disk-usage sudo du -sh /var/log/* | sort -h
推荐参数矩阵(按服务器类型)
类型 | Journald:SystemMaxUse | Journald:SystemMaxFileSize | Journald:SystemKeepFree | syslog:size | syslog:rotate |
---|---|---|---|---|---|
轻量实例(1–2GB RAM) | 400M | 100M | 300M | 50M | 5 |
通用 Web/应用 | 1G | 200M | 500M | 100M | 7 |
高并发/日志多 | 2G | 256M | 1G | 200M | 10 |
监控与告警(防止再次写满)
在没有额外监控系统时,可用简易脚本配合 cron
邮件告警:
sudo tee /usr/local/bin/check-log-usage.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
# 触发条件:/var/log 超过 2G 或 Journal 超过 1.5G
set -e
LOG_DIR_SIZE=$(du -s /var/log | awk '{print $1}') # KB
JOURNAL_SIZE=$(journalctl --disk-usage 2>/dev/null | awk '{print $3$4}' | sed 's/[^0-9.]//g')
# 将 KB 转换为 GB 粗略判断
if [ "$LOG_DIR_SIZE" -gt $((2*1024*1024)) ]; then
echo "[WARN] /var/log 超过 2G:$((LOG_DIR_SIZE/1024)) MB"
fi
# Journal 简易判断(需要持久化开启才有意义)
# 这里仅提示,不做自动清理,避免误删审计
EOF
sudo chmod +x /usr/local/bin/check-log-usage.sh
加入 cron
(每小时检查一次):
(crontab -l 2>/dev/null; echo "0 * * * * /usr/local/bin/check-log-usage.sh | mail -s 'Log usage alert' root") | crontab -
若未配置本地邮件,可改为写入文件再由外部采集:
/usr/local/bin/check-log-usage.sh >> /var/log/log-usage-monitor.log 2>&1
回滚与还原
- 恢复 journald 默认:将
/etc/systemd/journald.conf
恢复初始(或注释自定义键),删除/var/log/journal
目录(仅在你确认不再保留持久日志时),然后systemctl restart systemd-journald
。 - 撤销 logrotate 改动:还原
/etc/logrotate.d/rsyslog
备份文件,或删除新增条目,再执行sudo logrotate -d /etc/logrotate.conf
做一次“干跑”检查配置语法。
常见坑与排错
- 改了 journald 但占用没降:需要先
restart systemd-journald
,再用--vacuum-size
或--vacuum-time
收敛历史文件。 - logrotate 没触发:检查
/var/lib/logrotate/status
的时间,确认cron.daily
正常;手动执行sudo /etc/cron.daily/logrotate
看输出。 - 应用仍写入旧句柄:对于关键服务,考虑在
postrotate
中systemctl reload <service>
而非仅copytruncate
。 - 磁盘突然被吃满:除日志外,确认
/var/crash
、容器层、临时大文件(如备份/转储)是否占用;日志限制并不能处理非日志数据。
FAQ 继续(围绕“ubuntu20.04 系统日志大小限制”)
Q:Journal 与 /var/log 文本日志如何取舍?
生产上常用“二者并存”:Journal 方便结构化检索与早期排障,文本日志便于外部采集与长期归档。通过上限配合轮转即可控制总体积。
Q:是否能按天精确限制 Journal 保留?
20.04 建议用 journalctl --vacuum-time=Nd
做周期清理(配合 cron
),或控制体积为主(SystemMaxUse
)。
Q:如何只把 Journal 放到独立分区?
将 /var/log/journal
挂载到独立分区或磁盘(如 XFS/EXT4),然后 Storage=persistent
,即可将 Journal 与根分区解耦。
一键初始化脚本(可选)——落地“ubuntu20.04 系统日志大小限制”
脚本将:① 配置 systemd-journald
体积上限;② 写入 rsyslog
的轮转规则;③ 立即回收历史占用。请先确认数值符合你的磁盘容量与合规需求。
sudo tee /usr/local/sbin/init-log-limits.sh >/dev/null <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
# --------- 参数:按需修改 ----------
J_SYSTEM_MAX_USE="1G"
J_SYSTEM_KEEP_FREE="500M"
J_SYSTEM_MAX_FILE="200M"
J_SYSTEM_MAX_FILES="10"
J_RUNTIME_MAX_USE="200M"
J_RUNTIME_KEEP_FREE="50M"
SYSLOG_SIZE="100M"
SYSLOG_ROTATE="7"
AUTH_SIZE="50M"
AUTH_ROTATE="8"
APT_SIZE="30M"
APT_ROTATE="6"
# -----------------------------------
echo "[1/5] 配置 journald..."
sudo mkdir -p /var/log/journal
sudo install -m 0644 /dev/stdin /etc/systemd/journald.conf <<JEOF
[Journal]
Storage=persistent
SystemMaxUse=${J_SYSTEM_MAX_USE}
SystemKeepFree=${J_SYSTEM_KEEP_FREE}
SystemMaxFileSize=${J_SYSTEM_MAX_FILE}
SystemMaxFiles=${J_SYSTEM_MAX_FILES}
RuntimeMaxUse=${J_RUNTIME_MAX_USE}
RuntimeKeepFree=${J_RUNTIME_KEEP_FREE}
JEOF
echo "[2/5] 重启 journald..."
sudo systemctl restart systemd-journald
echo "[3/5] 写入 rsyslog 轮转规则..."
sudo install -m 0644 /dev/stdin /etc/logrotate.d/rsyslog <<LEOF
/var/log/syslog
{
daily
size ${SYSLOG_SIZE}
rotate ${SYSLOG_ROTATE}
compress
delaycompress
missingok
notifempty
copytruncate
create 640 syslog adm
sharedscripts
postrotate
reload rsyslog >/dev/null 2>&1 || true
endscript
}
/var/log/auth.log /var/log/kern.log /var/log/faillog
{
weekly
size ${AUTH_SIZE}
rotate ${AUTH_ROTATE}
compress
delaycompress
missingok
notifempty
copytruncate
create 640 syslog adm
sharedscripts
postrotate
reload rsyslog >/dev/null 2>&1 || true
endscript
}
/var/log/apt/history.log /var/log/apt/term.log /var/log/dpkg.log
{
monthly
size ${APT_SIZE}
rotate ${APT_ROTATE}
compress
delaycompress
missingok
notifempty
copytruncate
create 640 root adm
}
LEOF
echo "[4/5] 立即瘦身与轮转..."
sudo journalctl --vacuum-size="${J_SYSTEM_MAX_USE}" || true
sudo logrotate -f /etc/logrotate.conf || true
echo "[5/5] 验证占用..."
journalctl --disk-usage || true
sudo du -sh /var/log/* | sort -h | tail -n 20 || true
echo "完成:ubuntu20.04 系统日志大小限制 已应用。"
EOF
sudo chmod +x /usr/local/sbin/init-log-limits.sh
sudo /usr/local/sbin/init-log-limits.sh
服务专用规则:Nginx / MySQL / Docker
Nginx 日志轮转(避免占满磁盘)
Ubuntu 20.04 通常已有默认规则;如需“按大小触发 + 无损切换句柄”,可单独新增:
sudo tee /etc/logrotate.d/nginx-size >/dev/null <<'EOF'
/var/log/nginx/*.log {
weekly
size 100M
rotate 10
missingok
notifempty
compress
delaycompress
sharedscripts
postrotate
# 优雅切换日志文件句柄(优于 copytruncate)
[ -s /run/nginx.pid ] && kill -USR1 $(cat /run/nginx.pid)
endscript
}
EOF
sudo logrotate -f /etc/logrotate.conf
MySQL 日志轮转(按实际路径调整)
MySQL 8 在 Ubuntu 20.04 上常见错误日志路径为 /var/log/mysql/error.log
;如开启了通用/慢日志,请同步加入:
sudo tee /etc/logrotate.d/mysql-extra >/dev/null <<'EOF'
/var/log/mysql/*.log {
daily
size 50M
rotate 14
compress
delaycompress
missingok
notifempty
create 640 mysql adm
sharedscripts
postrotate
# 让 mysqld 重新打开日志(若使用文件日志)
test -x /usr/bin/mysqladmin || exit 0
/usr/bin/mysqladmin --defaults-file=/etc/mysql/debian.cnf flush-logs >/dev/null 2>&1 || true
endscript
}
EOF
sudo logrotate -f /etc/logrotate.conf
Docker 容器日志(不要用 logrotate;用守护进程级别限制)
默认 json-file 驱动会在 /var/lib/docker/containers/*/*.log
不断增大。正确做法是在 /etc/docker/daemon.json
里设定最大大小与保留份数:
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json >/dev/null <<'EOF'
{
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "5"
}
}
EOF
sudo systemctl restart docker
如需每个容器不同限制,可在 docker run
或 Compose 里覆盖 --log-opt
。
journald 防喷涌(限速参数)
在高并发或异常噪声场景,可启用写入限速,避免日志“洪水”影响 IO:
# 在 /etc/systemd/journald.conf 的 [Journal] 中追加
RateLimitIntervalSec=30s
RateLimitBurst=1000
表示在 30 秒窗口内最多接收 1000 条超限消息,超出将被丢弃并统计(可依业务调小)。
将 Journal 放到独立分区(进一步隔离风险)
- 准备分区/磁盘并格式化(示例:
/dev/vdb1
):sudo mkfs.ext4 -L journal /dev/vdb1
- 创建挂载点并迁移现有数据:
sudo systemctl stop systemd-journald sudo mkdir -p /var/log/journal sudo mount /dev/vdb1 /var/log/journal sudo chown -R root:systemd-journal /var/log/journal sudo chmod 2755 /var/log/journal sudo systemctl start systemd-journald
- 写入
/etc/fstab
永久挂载:echo 'LABEL=journal /var/log/journal ext4 defaults,noatime 0 2' | sudo tee -a /etc/fstab
这样,“ubuntu20.04 系统日志大小限制” 不仅靠参数控体积,还把 Journal 与根分区解耦,防止互相拖累。
周期清理策略(配合体积上限)
在已设定 SystemMaxUse
的前提下,可额外用 --vacuum-time
做“按天保留”:
(crontab -l 2>/dev/null; echo "13 3 * * * /usr/bin/journalctl --vacuum-time=14d") | crontab -
上例每日 03:13 清理,仅保留最近 14 天的 Journal。
审计/合规建议(示例基线)
- 生产最小保留:业务日志(文本)≥ 30 天,系统审计与安全日志 ≥ 90 天;体积上限由磁盘与采集频率共同约束。
- 归档与外送:把日志汇聚到 ELK/ClickHouse/云观测平台;本机仅保短期,降低“被写满”风险。
- 时间同步:启用
systemd-timesyncd
或 NTP,保证跨节点日志时序一致。
快速诊断清单(谁在撑爆磁盘?)
# 查看 /var/log 各文件体积排行(Top 20)
sudo du -ah /var/log | sort -h | tail -n 20
# 哪些进程仍握着“已删除”的大文件句柄(幽灵占用)
sudo lsof | grep '(deleted)'
# 最近 1 分钟内最热的日志写入对象
sudo find /var/log -type f -mmin -1 -printf "%T@ %p\n" | sort -n | tail -n 30 | awk '{print $2}'
# Journal 统计(占用与文件数)
journalctl --disk-usage
ls -lh /var/log/journal/*/*.journal 2>/dev/null | wc -l
长尾问答(更贴近检索词意图)
“ubuntu20.04 系统日志大小限制 不生效”怎么办?
确认 Storage=persistent
、目录存在、已 restart systemd-journald
,并执行一次 --vacuum-size
收敛历史文件。
“如何只限制 /var/log/syslog 体积,不影响其他日志?”
把 size
、rotate
等指令仅写入 /etc/logrotate.d/rsyslog
对应 /var/log/syslog
的条目,其它文件不改动。
“K8s/容器场景如何做 ubuntu20.04 系统日志大小限制?”
宿主机启用 journald 体积上限;容器引擎用 json-file
的 max-size
/max-file
;集群层面把应用日志外送到集中存储。