首页
/ SerenityOS chmod 命令完全指南:八进制与符号模式修改文件权限

SerenityOS chmod 命令完全指南:八进制与符号模式修改文件权限

2026-09-09 22:34:36作者:秋阔奎Evelyn

导读

本文基于 SerenityOS 操作系统的 chmod 手册页,系统讲解如何在 SerenityOS 中修改文件权限(file mode):既支持传统八进制数字模式,也支持 [ugoa][+-=][rwx...] 符号模式,并覆盖递归修改、setuid/setgid/sticky 特殊位等实战用法。文章同时结合仓库中 chmod 工具源码权限掩码解析库内核系统调用实现,从用户态到内核态还原权限修改的完整链路。读完本文,你将掌握在 SerenityOS 中精确控制文件访问权限的完整技能。

Name

chmod —— change file mode(修改文件模式)。

Synopsis

$ chmod <octal-mode> <path...>
$ chmod <mode> <path...>
  • <octal-mode>:八进制数字模式(如 750);
  • <mode>:符号模式(如 o+r);
  • <path...>:一个或多个目标文件路径,命令会依次处理全部路径。

chmod.cpp 中可以看到参数解析的实际定义:mode 是必需的位置参数,paths 是可变数量的位置参数,-R/--recursive 为可选选项。解析完成后,模式字符串被交给 Core::FilePermissionsMask::parse() 处理。

Description

chmodpath 中指定的所有文件的模式修改为 octal-mode(八进制)或符号表示形式。

符号表示形式的格式为 [[ugoa][+-=][rwx...],...],可以给出多个符号表达式,用逗号分隔。

符号模式语法详解

组成部分 取值 含义
用户类别 [ugoa] u file owner(文件属主)
g file owning group(文件所属组)
o others(其他用户)
a all users(全部用户)
操作符 [+-=] + 添加权限
- 移除权限
= 设置为仅包含指定权限,并取消其他权限
权限位 [rwx] r read(读,对应位值 4)
w write(写,对应位值 2)
x execute(执行,对应位值 1)

几个关键规则:

  • 未指定用户类别时默认 a:例如 +r 等价于 a+r。这一点在 FilePermissionsMask.cpp 中有明确实现——当解析器遇到操作符而 classes 仍为 0 时,会自动补全为 ClassFlag::All
  • = 会清空该类别其他权限:例如 g=r 表示组仅有读权限,之前组的写、执行权限都会被清除。
  • X 权限位:仓库实现还支持 X(大写),它表示"仅对目录或已有任一执行位的文件添加执行权限"。这对应 FilePermissionsMask.cpp 中的 directory_or_executable_mask 机制:apply() 时先判断 S_ISDIR(mode) || (mode & 0111) != 0,满足条件才应用该掩码(见 FilePermissionsMask.h)。
  • 多组表达式用逗号分隔:解析器在遇到逗号后回到 Classes 状态重新解析下一组(见 FilePermissionsMask.cpp)。
  • 错误校验:解析器对非法字符会返回明确的错误信息,例如 invalid class: expected 'u', 'g', 'o' or 'a'invalid operation: expected '+', '-' or '='invalid symbolic permission: expected 'r', 'w' or 'x',这些错误路径均有单元测试覆盖(见 TestLibCoreFilePermissionsMask.cpp)。

数字模式(八进制)详解

一个数字模式由 1 到 4 位数字组合而成,被省略的高位视为前导零。

  • 第一位数字:选择特殊属性——set user ID(4)、set group ID(2)和 restricted deletion / sticky(1);
  • 第二、三、四位数字:分别控制各用户类别的权限——属主(owner)、所属组(owning group)和其他用户(others),每类由 read(4)、write(2)和 execute(1)叠加而成。

例如 chmod 750 表示:属主为 7(rwx)、组为 5(r-x)、其他用户为 0(无权限)。

源码层面,八进制解析由 from_numeric_notation() 实现(见 FilePermissionsMask.cpp):使用 convert_to_uint_from_octal 将字符串按八进制解析为 mode_t,若超过 07777 则返回 invalid octal representation 错误。数字模式通过 assign_permissions() 直接设置写掩码并清空全部 0777 位,实现"整体替换"语义。

特殊位(setuid / setgid / sticky)行为说明

  • 使用 4 位数字(如 47117750)时,第一位会设置特殊位:4 为 setuid、2 为 setgid、1 为 sticky;
  • 使用 3 位数字(如 750)时,特殊位被清空——从源码看,assign_permissions 只设置写掩码、清空 0777,且当字符串长度 ≥ 4 时会显式移除 07000 特殊位(见 FilePermissionsMask.cpp)。

这些边界行为在 TestLibCoreFilePermissionsMask.cppnumeric_mask_special_bits 测试用例中有完整验证,例如 parse("7750").apply(0) == 07750parse("0750").apply(07000) == 0750

Options

  • -R, --recursive:递归修改文件模式

递归处理在 chmod.cpp 中实现:当目标是目录且开启了递归时,工具使用 Core::DirIterator(跳过 ...)遍历目录内所有条目,并对每个子项递归调用同一处理函数,因此可以正确处理嵌套目录树。任何一次递归操作失败都会累积到最终结果,最终以非零退出码报告失败。

权限修改的底层链路

理解 chmod 的底层原理有助于排查权限问题:

  1. 模式解析(用户态)chmod.cpp 调用 Core::FilePermissionsMask::parse(mode),该函数根据首字符是否为数字自动分派到八进制或符号解析器(见 FilePermissionsMask.cpp)。解析结果是一个由 m_clear_mask(要清除的位)与 m_write_mask(要设置的位)组成的掩码对象,最终通过 apply(stat.st_mode) 与文件现有模式运算得到新模式。
  2. 权限承诺(pledge):工具启动时调用 Core::System::pledge("stdio rpath fattr")(见 chmod.cpp),其中 fattr 承诺是执行文件属性修改类操作所必需的权限。
  3. 符号链接处理chmod 对符号链接有特殊策略——除非符号链接被显式列在命令行中,否则不会处理它;且由于 chmod 系统调用作用于链接指向的目标文件,工具会对显式给出的符号链接使用 stat() 重新获取真实目标文件的模式作为修改基准(见 chmod.cpp)。
  4. 内核系统调用:最终通过 chmod 系统调用完成修改。Kernel/Syscalls/chmod.cpp 展示了 sys$chmod 的实现:它校验 fattr pledge、从用户空间拷贝参数、解析路径,并调用 VirtualFileSystem::chmod();同文件还提供了基于文件描述符的 sys$fchmodfollow_symlinks 参数控制是否跟随符号链接。

Examples

# 属主拥有全部权限,组拥有读和执行权限,其他用户无任何权限:
$ chmod 750 README.md

# 将 '/bin/su' 设置为 set-uid,属主可读可写可执行,其他用户仅可执行:
# chmod 4711 /bin/su

# 为 'Source' 目录下所有文件添加其他用户的读权限:
$ chmod o+r Source/*

# 拒绝非属主的读写权限,并为属主开放全部权限:
$ chmod o-rw,g-rw,u+rwx script.sh

# 将 'script.sh' 的组权限设置为仅读:
$ chmod g=r script.sh

补充说明:

  • chmod 750 README.md 等价于符号形式 u=rwx,g=rx,o=TestLibCoreFilePermissionsMask.cpp 中的 file_permission_mask_parse 测试用例验证了 parse("750")parse("u=rwx,g=rx,o-rwx") 产生完全一致的 clear/write 掩码。
  • chmod 4711 /bin/su 中的 4 表示 setuid 位,注意原手册中该示例被注释掉,仅作演示用途。
  • 多组符号表达式逗号分隔的等价测试见 TestLibCoreFilePermissionsMask.cppu+rw,g=rx,o-rwx 的 clear 掩码为 0077、write 掩码为 0650,apply(0177) 得到 0750。

退出码与错误处理

chmod.cpp 的实现可以看到:

  • 所有路径处理成功时返回 0
  • 任一路径失败(如 stat 失败、chmod 失败、递归子项失败)时返回 1,且每个失败都会向标准错误输出 Could not stat '...'Failed to change permissions of '...' 形式的诊断信息。

这使得 chmod 可以安全地嵌入脚本:结合 &&set -e 时,权限修改失败会立即暴露,不会静默吞掉错误。

See also

  • chgrp(1)——修改文件所属组
  • chown(1)——修改文件属主与所属组

三者配合使用即可完整管理 SerenityOS 中文件的属主、属组与权限三元组。系统调用层面,chown/chgrp 同样依赖 fattr pledge,与 chmod 的权限模型一致。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
docsdocs
暂无描述
Markdown
900
5.83 K
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
860
1.35 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
927
1.85 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.84 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
533
603
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.37 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
397
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.04 K
525