首页 > Sysadmin > 正文

Linux 修改文件权限:chmod 的三种写法详解

huyuanwen 2026-10-28 Sysadmin

符号模式、八进制、–reference 参照文件,就是 chmod 手册语法里并列的三种写法。各适合什么场景、有哪些坑,均在 WSL 实测后写成。

一、三种写法对号入座,八进制怎么算

chmod 手册页的 SYNOPSIS 同时列了三种用法:符号模式(MODE)、八进制数字(OCTAL-MODE)、–reference=RFILE [1]。日常怎么选:

| 写法 | 例子 | 适合场景 | | — | — | — | | 符号模式 | chmod u+x s.sh | 只增删某一类位,其余不动 | | 八进制 | chmod 644 app.conf | 整体设定、脚本里成批处理 | | 参照文件 | chmod –reference=tmpl f | 照抄一个现成文件的权限 |

八进制每位是 r=4、w=2、x=1 的相加,依次对应属主、属组、其他人;可以在最前面再加一位,4、2、1 分别表示 setuid、setgid、sticky [3]。

: > f.txt && chmod 644 f.txt   # rw-r--r--
chmod 755 f.txt                # rwxr-xr-x
chmod u=rwx,go=rx f.txt        # 符号写法,与上一行等价(实测同结果)
chmod 0755 f.txt               # 三位前加 0,数字部分不变
chmod 888 f.txt                # invalid mode:八进制只有 0-7,退出码 1

644 给普通文件、755 给程序和目录,是最常见的两组数,但注意数字是”整体覆盖”:它会把没写到的位全部清掉,增量调整请用符号写法。

二、前导位与特殊位:sticky 的保留规则跟 setuid 不一样

: > run.sh && chmod 4755 run.sh   # -rwsr-xr-x
mkdir shared
chmod 2775 shared                 # drwxrwsr-x
chmod 1777 shared                 # drwxrwxrwt
chmod 755 shared                  # 实测:t 没了
stat -c '%a %A' shared            # 755 drwxr-xr-x

setuid 让脚本以属主身份运行,setgid 目录里新建文件继承目录的属组,sticky 目录(如 /tmp)里谁的文件谁能删,这三条语义见手册 [1][4],执行层面的行为基于文档、本文未逐一实测。要实测出真差距的是”数字改写时特殊位保不保得住”:

  • 文件:chmod 755 直接把 4755 变 755,setuid 被清(实测)。
  • 目录:手册口径是不带前导零的数字会保留 setuid/setgid,实测 4755 的目录跑 chmod 755 后仍是 4755 [4]。
  • 但 sticky 不在承诺范围内:1777 的目录跑 chmod 755 后变回 755,t 位没了(实测)。
  • 想明确清掉特殊位,就写前导零(00755)或用 = 形式,实测两种都会清零 [1]。
  • 也就是说,给共享目录补权限后,t 位要记得单独补一次 chmod 1777 或 +t。

    三、符号写法:who、操作符,还有 umask 的暗中干扰

    符号模式由三段组成:who(u 属主、g 属组、o 其他人、a 全部),操作符(+ 增、- 删、= 设定),再加权限字符 rwxXst;多段之间用逗号分隔 [1]。

    : > f.sh                       # 新文件默认 644
    chmod u+x f.sh                 # 变 744
    chmod a-w f.sh                 # -r-xr--r--
    chmod go-w f.sh                # 本来就没有 w:无变化,退出码仍 0
    mkdir -p conf.d && : > conf.d/plain.conf && : > conf.d/keep.sh
    chmod 644 conf.d/plain.conf && chmod 755 conf.d/keep.sh
    chmod -R a=rX conf.d           # 目录和"本来可执行"的文件才有 x

    a=rX 实测结果:conf.d 变 555,plain.conf 变 444,原本 755 的 keep.sh 保住 x 变 555。大写 X 的含义是”仅当目录或文件原本任一类有 x 才给 x”,给配置树批量加可读时比小写 x 安全 [3][2]。

    另一个不显眼但会白跑命令的点:省略 who 时(如 chmod +w),手册明确”等效 a,但 umask 里置位的权限不受影响” [3]。实测:umask 022 下对 600 的文件跑 chmod +w,纹丝不动;改成 umask 000 再跑变 622;而写 a+w 就不受 umask 影响。脚本里要精确放权,把 who 和 a 写全。

    四、参照写法 –reference:照抄权限

    : > app.conf && chmod 640 app.conf
    : > nginx.conf && : > proxy.conf
    chmod --reference=app.conf nginx.conf proxy.conf
    chmod -c --reference=app.conf proxy.conf
    # mode of 'proxy.conf' changed from 0644 (rw-r--r--) to 0640 (rw-r-----)

    –reference 把参照文件的权限整套复制过来,不用换算数字;手册注明参照文件若是软链接,取它指向文件的权限 [2]。实测两个文件都变 640;-c 会打出 changed from 明细,同权限重复执行则保持静默、退出码 0,想看 retained 行要换 -v [4]。参照文件本身是软链接的场景也实测通过,跟随指向取目标权限。批量对齐同一套权限、或恢复前先拿标准模板文件兜底,这条命令比挨个背八进制稳。

    五、软链接、递归和以破折号开头的文件名

    : > real.txt && ln -s real.txt link.txt
    chmod 600 link.txt         # 实际改的是 real.txt;link 本身仍 lrwxrwxrwx
    chmod -h 600 link.txt      # Ubuntu 24.04 实测报 invalid option -- 'h'
    mkdir logs && ln -s ../real.txt logs/inner.txt
    chmod -R go-rwx logs/      # 递归不跟进软链接指向的文件(实测)
    : > ./-w
    chmod -- -w ./-w           # 文件名以 - 开头:模式前插 -- 再改(实测)

    GNU 版 chmod 不改软链接本身,而是改它指向的文件;递归时忽略途中遇到的软链接,但命令行上直接给出的软链接仍会跟进指向目标 [2]。手册页里的 -h/–no-dereference 注明只在支持 lchmod 的系统可用,多数 Linux 上软链接自身权限本就被忽略 [1][4]——实测 Ubuntu 24.04 的 chmod(coreutils 9.4)根本没有 -h 这个选项,抄了 chmod -h 的教程会直接报错,不用纠结。文件名以 – 开头时按手册示例先写 — [2]。另外实测:非属主的普通用户 chmod 别人的文件报 Operation not permitted,chown 给该用户后自己就能改,这是”改不了权限”类求助的第一嫌疑。

    六、撤销、回滚与排错速查

    chmod 没有 undo。稳妥流程:动手前先 stat -c '%a %n' 目标/* > /tmp/perm.bak 记录现值(实测可用),再改;恢复时按记录逐行改回,或从标准模板文件 chmod --reference=模板 目标 整体复原。递归操作(chmod -R、777)动手前尤其要先备份权限记录,范围先在小目录验证再放大。

    | 现象 | 原因 | 处理 | | — | — | — | | invalid mode: ‘888’ | 数字模式是八进制,只认 0-7 | 检查是否误用十进制 | | invalid mode: ‘u+x,’ | 符号段用逗号分隔,结尾多逗号非法 | 删掉末尾逗号(实测) | | chmod +w 没反应 | 省略 who 时被 umask 屏蔽 | 显式写 a+w | | invalid option — ‘h’ | 该发行版的 chmod 未编译 -h | 无需改软链接本身,Linux 会忽略其权限 | | 改权限报 Operation not permitted | 非属主且非 root | 由属主或 root 执行 | | 目录突然不能写文件 | = 形式或数字清掉了 sticky/写位 | 按 /tmp/perm.bak 恢复,必要时补 +t |

    局限性:本文全部命令在 WSL2 ext4 上实测;NFS、drvfs 等特殊文件系统对权限位的处理(尤其 setuid/sticky 是否生效)未覆盖,RPM 系发行版未单独复测,操作前先在目标环境验证。

    ## 附:实测记录

  • 测试机:WSL2(内核 6.6.114.1-microsoft-standard-WSL2)、Ubuntu 24.04.4 LTS、chmod (GNU coreutils) 9.4、ext4,2026-10-27 以 root 执行,临时目录与测试用户已清理。
  • 数字与符号:644/755/0755 与 u=rwx,go=rx 结果一致;chmod 888 报 invalid mode,退出码 1;chmod ‘u+x,’ 同样报 invalid mode。
  • 特殊位:4755 文件显 -rwsr-xr-x,2775 目录显 drwxrwsr-x,1777 目录显 drwxrwxrwt;4755 目录 chmod 755 后仍 4755,1777 目录 chmod 755 后变 755(t 被清);文件 4755 跑 755、00755、=755 均变 755。
  • 符号与 umask:umask 022 时 +w 对 600 文件无变化,umask 000 时变 622;a+w 不受 umask 077 影响变 622;-R a=rX 后目录 555、644 文件 444、755 文件 555。
  • 参照与链接:–reference 两文件同变 640,-c 打印 changed 明细、重复执行静默(-v 才打 retained);参照为软链接时跟随指向;chmod 600 作用于软链接时目标变 600、链接保持 777;-R go-rwx 不影响链接指向的目标文件;chmod — -w ./-w 成功变 444;chmod -h 报 invalid option,–help 亦无该选项。
  • 非属主:普通用户 chmod root 文件报 Operation not permitted(退出码 1),chown 后自行 chmod 成功。
  • 未验证:setuid 程序实际执行身份、setgid 目录属组继承的端到端行为(基于文档描述);NFS/drvfs 下特殊位表现。

  • 参考资料

    文中主要命令已在 WSL Ubuntu(24.04)实测并核对其在 Debian 系与通用发行版的文档口径。