date在日志切割中出错因默认输出含空格、斜杠等非法文件名字符,且Linux与macOS的date命令语法不兼容(如-d不被BSD date支持),须统一用%Y%m%d_%H%M%S等安全格式并加引号包裹。

date 指令在日志切割中为什么总出错
因为 date 默认输出带空格和斜杠的格式(如 2024-05-22 14:30:45),直接拼进文件名会触发 shell 分词或路径解析失败;更隐蔽的问题是,不同系统(macOS / Linux)的 date 对 -d、-v、%s 支持不一致,脚本一换环境就报 invalid date format 或静默输出空字符串。
Linux 下用 GNU date 生成安全文件名
核心原则:只用字母、数字、下划线、短横线,避免空格、冒号、斜杠。推荐固定格式 %Y%m%d_%H%M%S:
-
date +%Y%m%d_%H%M%S→20240522_143045(最常用,无歧义) -
date -d 'yesterday' +%Y%m%d→ 获取昨日日期(仅 GNU date 支持-d) - 若需时间戳秒级精度但不用可读格式:
date +%s(注意:该值是 Unix 时间戳,跨平台兼容性好) - 避免用
%F %T—— 它等价于%Y-%m-%d %H:%M:%S,含空格和冒号,不能直接当文件名
macOS 上 date 不支持 -d 怎么办
macOS 自带 BSD date,不认 -d,但支持 -v 偏移语法,且必须配合 -f 指定输入格式才能做计算:
- 获取今天:
date +%Y%m%d_%H%M%S(基础格式两者都支持) - 获取昨天:
date -v-1d +%Y%m%d(-v-1d表示减一天) - 获取 3 小时前:
date -v-3H +%Y%m%d_%H%M%S - 想兼容 Linux 和 macOS?绕过
-d和-v,改用$(($(date +%s) - 86400))算秒数再转格式,例如:date -r $(( $(date +%s) - 86400 )) +%Y%m%d(macOS 支持-r,Linux 需用@:date -d @$(($SECONDS - 86400)) +%Y%m%d)
脚本里调用 date 的三个硬约束
写进日志切割脚本(比如 logrotate 配置中的 prerotate 或自定义 shell 脚本)时,必须检查:
- 确保
date命令在 PATH 中,不要写绝对路径(如/bin/date)除非明确知道目标系统位置 - 所有
date调用必须用反引号或$()包裹,且变量赋值时加双引号:ts="$(date +%Y%m%d_%H%M%S)",否则空格会导致后续mv或gzip失败 - 如果脚本可能被 cron 执行,注意 cron 默认
LANG=C,可能导致某些 locale 相关格式符(如%B)输出为空,一律用纯 ASCII 格式符(%Y、%m、%d等)
真正麻烦的不是记不住格式符,而是同一行脚本在测试机跑通,上线后因系统差异或 cron 环境缺失变量而切割失败——建议把 date 调用单独抽成函数,并在开头加 date --version 2>/dev/null | head -1 判断类型。


















