需求背景:
由于docker容器每次重新构建后,日志都会丢失 导致没法追溯,定位故障等,痛!需求实现:
本次采用Shell脚本+systemd服务来启动和管理服务
一、创建脚本docker-log.sh
#!/bin/bash
# 设定备份时间间隔为30秒
BACKUP_INTERVAL=30
# 设定保留备份文件的天数
RETAIN_DAYS=3
# 设定日志文件名
LOG_FILE="/var/log-bak/backup.log"
# 设定上次备份时间文件名
LAST_TIME_FILE="/var/log-bak/last_time.txt"
# 设定日志目录为当天的日期
LOG_DIR="/var/log-bak/$(date +%Y%m%d)"
if [ ! -d "$LOG_DIR" ]; then
# 如果日志目录不存在,则创建该目录
mkdir -p "$LOG_DIR"
fi
if [ ! -f "$LAST_TIME_FILE" ]; then
# 如果上次备份时间文件不存在,则创建该文件,并写入当前时间和容器名
touch "$LAST_TIME_FILE"
for CONTAINER_NAME in $(docker ps --format "{{.Names}}"); do
echo "$CONTAINER_NAME $(date +%s)" >> "$LAST_TIME_FILE"
done
fi
while true; do
# **重新设定日志目录为当前日期**
LOG_DIR="/var/log-bak/$(date +%Y%m%d)"
if [ ! -d "$LOG_DIR" ]; then
# 如果日志目录不存在,则创建该目录
mkdir -p "$LOG_DIR"
fi
# 循环遍历docker中所有容器名和对应的容器ID
for CONTAINER_NAME in $(docker ps --format "{{.Names}}"); do
# 定义备份文件名
LOG_BACKUP_FILE="${LOG_DIR}/${CONTAINER_NAME}.log"
if [ ! -f "$LOG_BACKUP_FILE" ]; then
# 如果备份文件不存在,则创建该文件
touch "$LOG_BACKUP_FILE"
fi
# 从上次备份时间文件中读取对应容器的最后一次备份时间,并赋值给LAST_TIME变量
LAST_TIME=$(grep "$CONTAINER_NAME" "$LAST_TIME_FILE" | tail -n 1 | cut -d ' ' -f 2)
# 通过docker logs命令获取自上次备份时间以来新增的日志并追加到备份文件中
docker logs --timestamps --since "$LAST_TIME" "$CONTAINER_NAME" >> "$LOG_BACKUP_FILE"
# 向日志文件中写入备份的容器名和时间
echo "[$(date)] Backed up $CONTAINER_NAME log to $LOG_BACKUP_FILE" >> "$LOG_FILE"
# 更新上次备份时间为当前时间,并写入到上次备份时间文件中,附带容器名
echo "$CONTAINER_NAME $(date +%s)" >> "$LAST_TIME_FILE"
done
# 删除过期的备份文件,只保留最近3天的备份文件,并向日志文件中写入删除的文件名和时间
find /var/log-bak/202*/ -type f -mtime +$RETAIN_DAYS -delete -print | xargs -I {} echo "[$(date)] Deleted expired backup file {}" >> "$LOG_FILE"
# 休眠备份时间间隔后继续下一轮备份
sleep $BACKUP_INTERVAL
done
二、创建/etc/systemd/system/log-backup.service文件
[Unit]
Description=Log backup service
After=docker.service
[Service]
User=root
WorkingDirectory=/var/log-bak
ExecStart=/bin/bash /var/log-bak/docker-log.sh
PIDFile=/var/run/log-backup.pid
ExecStartPre=/bin/rm -f /var/run/log-backup.pid
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
配置解释:
User 指定了执行该服务的用户
WorkingDirectory 指定了服务工作目录
ExecStart 指定了要执行的Shell脚本
Restart和RestartSec 指定了服务重启的策略
After 指定了服务依赖项,这里设置为docker.service,表示在Docker服务启动后再启动该服务
PIDFile 确保每次只有一个实例在运行
ExecStartPre 会在服务启动前删除旧的PID文件
三、服务管理
systemctl daemon-reload # 重新加载systemd配置文件
systemctl enable log-backup # 启用服务自启动
systemctl start log-backup # 启动服务
systemctl stop log-backup # 停止服务
systemctl disable log-backup # 禁用服务自启动