date 命令需用 %3N 获取毫秒级时间戳,如 date +'%Y%m%d_%H%M%S_%3N';老旧系统不支持时可用 %N 截取或结合 PID 避免冲突,容器/云环境还需考虑时间漂移问题。

用 date 命令生成带毫秒级精度的时间戳
默认 date 不输出毫秒,直接 date +%s 只有秒级,高并发下容易撞名。得靠 %N(纳秒)配合字符串截取来模拟毫秒——Linux 的 date 支持 %3N 直接取前三位纳秒数字:
mkdir -p "/tmp/myapp_$(date +'%Y%m%d_%H%M%S_%3N')"
注意:%3N 在较老的 GNU coreutils(invalid date format,改用以下兼容写法:
-
date +%s%3N→ 若不支持, fallback 到$(date +%s)$(printf "%03d" $((RANDOM % 1000))) - 避免用
$SECONDS或$(uptime -s),它们没毫秒、不可靠、非单调
为什么不用 mktemp -d?它不按时间戳命名
mktemp -d 确实最安全(自动防竞态、权限正确),但它生成的是类似 /tmp/tmp.XXXXXX 的随机后缀,无法满足「按时间戳命名」这个硬性需求——比如日志归档、调试回溯时要一眼看出创建时刻。
如果只要防重复+可读性兼顾,可以折中:
dir=$(mktemp -d "/tmp/myapp_$(date +'%Y%m%d_%H%M%S').XXXXXX")
这样既保留时间前缀便于识别,又靠 XXXXXX 避免手动拼接导致的竞态(比如两个进程同时执行到 mkdir 前,date 输出相同,就真会报 File exists)。
实际脚本里必须加错误检查和清理逻辑
时间戳命名只是第一步,真正落地时容易忽略三件事:目录是否真创建成功、是否被其他进程抢先占位、出错后要不要删残留。
- 永远用
if ! mkdir "$dir"; then echo "fail: $dir exists or permission denied"; exit 1; fi,别只靠set -e - 临时目录建议统一挂到
/tmp下,避免用户家目录满或 noexec 挂载导致失败 - 若脚本可能中断,加
trap 'rm -rf "$dir"' EXIT,但注意EXIT对kill -9无效
跨时区或 NTP 调整时,时间戳可能“倒流”
如果系统时间被 NTP 向后大幅校正(比如从 10:00:05 回拨到 10:00:03),连续两次 date 调用可能产生递减的时间戳——导致后续生成的目录名字典序小于前一个,破坏“时间越新目录名越靠后”的假设。
解决办法不是禁用 NTP(不现实),而是:
- 对时间戳做简单去重:先
stat -c '%Y' "$last_dir" 2>/dev/null比较上一次创建时间,若当前$(date +%s)小于它,主动 sleep 0.01s 再试 - 或者彻底放弃纯时间戳,改用
$(date +%s)_$$(PID)组合,PID 天然唯一且不会倒流
真正难处理的从来不是格式,是时间本身的不确定性——尤其当你的脚本要跑在容器里、云主机上,或是被 systemd 定时拉起的时候。











