HCRM博客

CentOS Shell脚本,获取昨天日期并打包日志的方法

CentOS shell如何获取昨天日期并打包日志?

服务器日志天天涨,磁盘报警比闹钟还准时。想自动把昨天的日志打包甩到备份目录,还要让文件名带上日期,手动改名字太掉价,一条shell命令就能解决,却总有人卡在“昨天日期怎么算”这一步。下面把最简方案直接甩出来,复制就能用,顺便把坑填平。

CentOS Shell脚本,获取昨天日期并打包日志的方法-图1

为什么非要“昨天”而不是“前天”

日志是按天切割,零点一过新文件生成,旧文件立刻停止写入。此时打包不会触发“文件被占用”的警告,压缩率也最高。若等到第三天再处理,中间可能又被日志清理脚本删了,哭都来不及。

获取昨天日期的三种写法

写法一:date -d 最常用

date -d "1 day ago" +%Y%m%d

输出形如 20240618,直接当字符串用。CentOS 7 默认 GNU date,-d 参数支持自然语言“1 day ago”,别写成“-1 day”,老版本会报错。

CentOS Shell脚本,获取昨天日期并打包日志的方法-图2

写法二:相对秒数计算

date -d @$(( $(date +%s) - 86400 )) +%Y%m%d

86400 是一天的秒数,适合写脚本里,避免不同语言环境把“day ago”翻译成“日前”导致失败。

写法三:纯busybox环境

某些极简容器只有 busybox,date 不支持 -d,用 awk 硬算:

awk 'BEGIN{print strftime("%Y%m%d", systime()-86400)}'

CentOS Shell脚本,获取昨天日期并打包日志的方法-图3

三选一即可,别混用,保持脚本风格统一。

一条命令打包昨天日志

假设日志放在 /var/log/nginx,每天生成 access.log 和 error.log,零点切割后变成 access.log-20240618 这种后缀。想把昨天的俩文件一起压成 gzip,并放到 /backup/nginx,命令如下:

yesterday=$(date -d "1 day ago" +%Y%m%d) && tar -czf /backup/nginx/nginx-${yesterday}.tar.gz -C /var/log/nginx $(ls /var/log/nginx/*-${yesterday} 2>/dev/null)

解释:

1. yesterday 变量先算好,后面多处引用,避免多次执行 date 命令。

2. tar 的 -C 参数切换目录,打包时文件路径不带长目录,解压更干净。

3. ls 后面跟通配符,只匹配昨天后缀的文件,2>/dev/null 防止空列表报错。

4. 如果日志命名规则是 .log.20240618,把通配符改成 *.log.${yesterday} 即可。

整点自动跑,交给 crontab

每天两点十分执行,避开日志切割时间:

10 2 * /bin/bash /opt/scripts/packnginxlog.sh >/dev/null 2>&1

脚本内容拆出来,方便调试:

#!/bin/bash

backup_dir="/backup/nginx"

log_dir="/var/log/nginx"

yesterday=$(date -d "1 day ago" +%Y%m%d)

mkdir -p "$backup_dir"

files=$(ls $log_dir/*-${yesterday} 2>/dev/null)

if [ -n "$files" ]; then

tar -czf "$backupdir/nginx-${yesterday}.tar.gz" -C "$logdir" $files

fi

加完权限 chmod +x,丢到 /opt/scripts,crontab 直接调。

多目录循环打包,一个 for 全搞定

系统里除了 nginx,还有 tomcat、php-fpm,目录不同,命名规则却一样,用 for 循环最省事:

yesterday=$(date -d "1 day ago" +%Y%m%d)

for app in nginx tomcat php-fpm; do

log_dir="/var/log/$app"

backup_dir="/backup/$app"

mkdir -p "$backup_dir"

files=$(ls $log_dir/*-${yesterday} 2>/dev/null)

[ -n "$files" ] && tar -czf "$backupdir/${app}-${yesterday}.tar.gz" -C "$logdir" $files

done

新增应用只要在 for 里加空格隔开,脚本零改动。

打包后顺手删旧备份,只留七天

磁盘再大也扛不住只写不删,find 一行清掉七天前的包:

find /backup -name "*.tar.gz" -mtime +7 -delete

加到脚本末尾,打包完成立即执行,避免另起定时任务忘记配。

文件名想带横杠或下划线?改格式串

有人习惯 2024-06-18,把 +%Y%m%d 换成 +%F 即可;想要 20240618 就写 +%Y%m%d。格式串一次到位,后面所有脚本统一,别今天横杠明天下划线,自己给自己埋雷。

打包失败如何告警

tar 返回非零代表失败,脚本里捕捉 exit code,发邮件或调钉钉机器人:

tar -czf "$backupdir/nginx-${yesterday}.tar.gz" -C "$logdir" $files

if [ $? -ne 0 ]; then

echo "打包失败:nginx ${yesterday}" | mail -s "日志备份告警" admin@example.com

fi

邮件服务没装,用 curl 调群机器人一样行,只要 exit code 判断准,告警就不会漏。

常见翻车点速查

1. 日期变量没引号,文件名带空格直接炸。

2. 系统语言是中文,date -d “1 day ago” 被本地化翻译失败,提前 export LC_ALL=C。

3. 日志切割脚本和打包脚本同时跑,tar 刚好读到被重命名的半拉文件,加锁文件或错开五分钟。

4. 备份目录没写权限,tar 创建文件失败,却忘了看错误输出,以为命令无效。

5. 手动测试成功,crontab 里失败,八成是没写绝对路径,tar、date、ls 全写 /bin/date 最保险。

小结

CentOS 下拿昨天日期就是 date -d “1 day ago” 一句话,配合 tar 通配符打包,十分钟写完脚本,丢进 crontab 就能躺平。变量引号、路径权限、错误码判断三步到位,再也不怕磁盘爆满。脚本越短,坑越少,跑稳了才是硬道理。

本站部分图片及内容来源网络,版权归原作者所有,转载目的为传递知识,不代表本站立场。若侵权或违规联系Email:zjx77377423@163.com 核实后第一时间删除。 转载请注明出处:https://blog.huochengrm.cn/pc/41701.html

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
请登录后评论...
游客游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~