在非交互式 Shell 脚本中,必须在 shebang 后立即设置 umask 077(如 #!/bin/bash\numask 077),以确保新文件默认权限为 600、目录为 700;需避免显式指定权限的命令绕过 umask,并在关键输出后补充 chmod 加固,systemd 或 cron 环境下也须脚本内显式设置。

在非交互式 Shell 脚本中,umask 不能靠修改 ~/.bashrc 或 ~/.profile 生效,因为这些文件默认不被读取。要让脚本内创建的文件严格只读(比如防止其他用户读取敏感数据),需在脚本开头显式设置 umask,并确保后续命令不绕过它。
直接在脚本顶部设 umask
这是最可靠的方式:在脚本第一行 shebang 后立即调用 umask,且不依赖任何 shell 初始化逻辑。
- 脚本开头写:#!/bin/bash
umask 077 —— 这会让新文件默认为 600,目录为 700 - 如果只需“只读”(即禁止写、执行,但允许读),且仅限当前用户可读,用 umask 077 即可;若还需禁止组和其他人读,也满足要求
- 注意:umask 是继承式的,子 shell 和大多数命令(如 touch、cp、mkdir)都会遵守它,除非显式指定权限(如 mkdir -m 755)
避免权限被覆盖的常见陷阱
即使 umask 设对了,生成的文件仍可能意外可读,原因常出在工具链上:
- 显式指定权限的命令会忽略 umask:例如 mkdir -m 755 dir、touch -m 644 file、cp --preserve=mode 都跳过 umask
- 某些程序内部硬编码 mode:如 rsync 默认用 644/755,除非加 --chmod 参数覆盖
- 重定向创建文件时受 umask 控制:echo "data" > out.txt 是安全的;但 echo "data" | tee out.txt 也遵循 umask
对关键输出做二次加固
仅靠 umask 不够保险,尤其当脚本调用外部工具或权限逻辑复杂时,建议补充 chmod:
- 生成文件后立刻收紧:touch data.txt && chmod 400 data.txt
- 用 set -o pipefail 配合 umask 077,确保整个流程不漏权限
- 若用 Python 或 Perl 等语言生成内容,记得调用 os.chmod() 或等效函数,因为它们不受 shell umask 影响(Python 的 open() 创建文件时仍受 umask 控制,但可后续修正)
systemd 或 cron 场景要单独处理
如果你的脚本由 systemd timer 或 crontab 触发,它们默认不加载用户 profile,所以脚本里必须自己设 umask:
- crontab 中可加环境变量:UMASK=077(部分 cron 支持);更通用的做法是脚本第一行就写 umask 077
- systemd 用户服务 unit 文件中,在 [Service] 段添加:UMask=0077(注意:这里写的是十进制 0077,实际等效于八进制 077)











