`chmod 0700` 后权限仍为 2700

kjo*_*kjo 7 permissions chmod

例子:

# show starting permissions
% stat -c '%04a' ~/testdir
0700

# change permissions to 2700
% chmod 2700 ~/testdir

# check
% stat -c '%04a' ~/testdir
2700

# so far so good...

# now, change permissions back to 0700
% chmod 0700 ~/testdir

# check
% stat -c '%04a' ~/testdir
2700

# huh???

# try a different tack
% chmod g-w ~/testdir
% stat -c '%04a' ~/testdir
0700
Run Code Online (Sandbox Code Playgroud)

错误或功能?

为什么chmod 0700 ~/testdir无法将权限从 更改27000700

我在几个不同的文件系统中观察到了相同的行为。例如,在最新的一个中,mount的输出的相关行是

/dev/sda5 on / type ext4 (rw,relatime,errors=remount-ro,data=ordered)
Run Code Online (Sandbox Code Playgroud)

此外,FWIW

% stat -c '%04a' ~/
0755
Run Code Online (Sandbox Code Playgroud)

Ste*_*itt 20

假设您使用的是 GNU chmod,这在手册页中有记录

chmod 除非您明确指定,否则保留目录的 set-user-ID 和 set-group-ID 位。您可以设置或象征性的模式,如清除该位u+sg-s,并可以设置(但不清除)位与数字模式。

这在POSIX 中是允许的:

对于八进制数中设置的每一位,应设置下表所示的相应文件权限位;应清除所有其他文件权限位。对于常规文件,对于set-user-ID-on-execution或set-group-ID-on-execution对应的八进制数中设置的每一位,应设置下表所示的位;如果这些位未在八进制数中设置,则它们将被清除。对于其他文件类型,是否接受设置或清除 set-user-ID-on-execution 或 set-group-ID-on-execution 位的请求由实现定义。

GNU 中的行为推理在6.0chmod发行说明中coreutils给出:

chmod, install,mkdir现在保留目录的 set-user-ID 和 set-group-ID 位,除非您明确要求。例如, chmod 755 DIRchmod u=rwx,go=rx DIR现在保存DIR的设置用户ID和设置组ID比特,而不是清除它们,并且类似地用于mkdir -m 755 DIRmkdir -m u=rwx,go=rx DIR。要清除这些位,请以符号模式明确提及它们,例如, mkdir -m u=rwx,go=rx,-s DIR。要设置它们,请以符号或数字模式明确提及它们,例如mkdir -m 2755 DIRmkdir -m u=rwx,go=rx,g+s DIR. 此更改是为了方便这些位从父项继承的系统。不幸的是,其他操作系统在这里不一致,并且可移植脚本不能假设这些位被设置、清除或保留,即使这些位被明确提及。例如,OpenBSD 3.9mkdir -m 777 D保留了D的 setgid 位但将其chmod 777 D清除。相反,Solaris 10 mkdir -m 777 Dmkdir -m g-s Dchmod 0777 D都保留D的 setgid 位,您必须使用类似的东西chmod g-s D来清除它。

#8391 中有更多关于这个主题的内容,包括前导 0 不明确的进一步理由(它可能表示用户心目中的已清除位或八进制值)。该coreutils手册还有一个专门的部分,目录和 Set-User-ID 和 Set-Group-ID 位;这表明存在允许清除相关位的 GNU 扩展:

chmod =700 ~/testdir
chmod 00700 ~/testdir
Run Code Online (Sandbox Code Playgroud)

两者都清除位(但不可移植)。