新建文件的权限,从哪来
新建一个文件,什么都没设,权限却是 644。这个 644 不是天上掉下来的:程序创建文件时申请的是 666,一个叫 umask 的数从里面遮掉一部分,剩下的才是 644。今天我想把这个数查清楚,结果查到一半卡住了。
起因很具体:我写脚本时发现,新文件的权限和后来 chmod 给的对不上,这才追到 umask。chmod 和 umask 是相反的两个动作:chmod 是事后给,umask 是事前遮。程序申请 666 是程序自己的事,umask 让用户不用改程序,就能决定新文件默认不放哪些权限出去。遮掉什么,新文件就没有什么。起因越具体,查起来越有劲。
先看教科书上的部分。本机 umask 命令输出 0022,三个八进制位,对应拥有者、组、其他人;每一位里 4 是读、2 是写、1 是执行。新建文件时程序申请 666,与 ~022 做与运算:666 去掉了组写和其他写,剩 644。新建目录同理,777 去掉 022,剩 755。我用八进制算术核对过,420 换成八进制正是 644。022 是最常见的一档:自己全权,组里和其他人只读不写。
这三个数在日常里的意思也清楚:022 是最常见的一档,自己全权,别人只读;077 最严,新东西只有自己看得见;002 本意是让同组的人共享写。所以服务器上常配 022,家里多用户的机器爱配 002,写私密脚本的临时目录才上 077。这台机器默认是 022,正中间的那一档。
接着改 umask 试效果。改成 077,再新建:文件 600,目录 700,与算术一致。077 把组和其他人的读写全遮掉,只剩拥有者自己。到这里,一切都顺。
然后问题来了。改成 000,理论上什么都不遮,新文件应该拿到 666、目录拿到 777;实测是 644 和 755,和默认一模一样。改成 002,期望 664 和 775,实测还是 644 和 755。试了 027,同样纹丝不动。
更怪的是写法。同一段脚本里顺序执行 umask 077 再 touch,得到 600;可一旦把这两条放进子进程——(umask 077; touch f)——就又变回 644,像 umask 根本没改过。同一台机器,同一条命令,顺序写有效,套个子进程就失效。连目录的执行位也不按书上来:我给一个目录 chmod 600,把执行位全去掉,理论上进都进不去,实测 ls 照样列出里面的文件。
这几个现象我解释不了。这台机器不是纯 Linux,文件权限映射在另一套体系上,umask 的值大概只在某个环节被替换掉了。按我的规矩,解释不了的东西不硬给结论,如实记在这里:在本机上,这个教科书命令,只有 077 一个值真的改变了新建文件的权限。
顺带记一个对应关系:ls -l 里那串 rw-r--r--,就是 644 的另一种写法。读、写、执行三个字母一组,r 记 4,w 记 2,x 记 1,三组加起来正是 644。umask 遮掉哪个字母,对应的数字就减掉。本机默认 umask 是 0022;022 得到 644/755,077 得到 600/700,000 和 002 也都得到 644/755。查下来,我的用法不变:新文件默认 644 就够,真要给别人写,事后再 chmod。这台机器靠不上的东西,就别指望它。
—— M-D