最稳妥方式是用 mktemp -d 创建随机临时目录并显式 chmod 0700,避免用户名拼接或依赖 umask;容器或 systemd 服务需隔离路径,清理须用 systemd-tmpfiles 或定期 find 删除,不可依赖 trap。
用 mktemp -d 生成用户专属临时目录最稳妥
直接用 mktemp -d 创建带随机后缀的目录,比拼接用户名或时间戳安全得多。它依赖系统熵池生成不可预测路径,避免目录名被猜解或碰撞。
- 错误做法:
mkdir /tmp/$USER-tmp—— 用户名可枚举,目录可被提前创建或覆盖 - 正确写法:
tmpdir=$(mktemp -d),然后chown $USER:$USER $tmpdir - 注意:某些旧版
mktemp(如 BusyBox)不支持-d,需先检查mktemp --version或 fallback 到mktemp -u+mkdir - 若需固定前缀(如日志隔离),用
mktemp -d "/tmp/${USER}_XXXXXX",但XXXXXX必须在末尾且不少于 6 个 X
chmod 0700 是硬性门槛,别信 umask
umask 不可靠——它只影响新建文件的默认权限,而临时目录一旦被创建,后续所有子进程、脚本、甚至其他用户的 sudo 操作都可能绕过它。显式设权才是唯一保险方式。
- 必须执行:
chmod 0700 $tmpdir,不能只靠umask 077 - 如果目录已存在(比如复用场景),
chmod前要加test -d $tmpdir && chmod 0700 $tmpdir防错 - 注意 SELinux 或 AppArmor 环境下,即使权限是 0700,策略也可能拒绝访问,需确认上下文标签(如
ls -Z $tmpdir)
容器或 systemd 服务里别直接用 /tmp
宿主机的 /tmp 对容器是共享的,systemd 服务默认也跑在全局命名空间里。用户 A 的临时目录可能被用户 B 的同名服务意外清理,或被容器挂载覆盖。
- 容器内应挂载独立卷:
docker run -v $(mktemp -d):/app/tmp ...,而非-v /tmp:/hosttmp - systemd 服务要用
PrivateTmp=yes,它会为每个服务实例自动创建隔离的/tmp,底层仍是mktemp -d衍生 - 若必须用宿主机路径,改用
/run/user/$(id -u)(systemd user session 下有效),它天然按 UID 隔离且内存驻留
清理时机比创建更关键:别等进程退出再删
靠 trap 'rm -rf $tmpdir' EXIT 很危险——进程被 SIGKILL、OOM killer 干掉时,trap 不触发,目录就永久残留。得有兜底机制。
- 优先用
systemd-tmpfiles:写规则到/etc/tmpfiles.d/myapp.conf,指定d /run/myapp/%U 0700 %U %U 1d,自动按用户和过期时间清理 - 若无 systemd,用
find /tmp -maxdepth 1 -name "*-tmp" -user $USER -mmin +60 -delete 2>/dev/null定期清理,但注意避免误删其他进程正在用的目录 - 绝对不要在
/tmp下用at或sleep启动延迟删除——系统重启后这些任务就丢了
临时目录的安全本质不在“随机”,而在“隔离+及时销毁”。很多人卡在 chmod 漏设或清理无保障上,一出问题就是越权读取或磁盘占满。

















