1. 文件权限:每个动手操作过Linux或macOS的人都绕不开的“门禁系统”
你有没有遇到过这样的情况:明明文件就放在自己电脑里,双击却提示“权限不足”;用命令行想删掉一个日志文件,系统冷冷回你一句Permission denied;写好了一个脚本,chmod都没动过,一执行就报错command not found或者Operation not permitted;甚至在团队协作时,同事传来的压缩包解压后一堆文件全是只读,连改个配置都得先sudo chmod -R 755 .才敢下手——结果一通操作猛如虎,回头发现把整个项目目录的执行位全开了,Git提交记录里全是mode change 100644 => 100755的噪音。
这些不是玄学,也不是系统故意刁难,而是文件权限机制在真实世界里的每一次呼吸与心跳。它不是教科书里那个“rwx三组九位”的静态快照,而是一套精密运转的访问控制逻辑,像一栋写字楼的门禁卡系统:前台(owner)有全楼通行卡,部门主管(group)能进本层办公区,访客(others)只能在大堂等候——而每扇门(文件/目录)上还贴着独立的准入标签(权限位)。你敲ls -l看到的-rw-r--r--,本质是操作系统在说:“这个文本文件,主人可读可写,同组人和外人都只能看,谁也别想运行它”。
我从2012年开始带某高校实验室的Linux系统运维实训,每年都会重演同一幕:学生第一次用vim编辑/etc/hosts,保存时弹出E212: Can't open file for writing;有人为图省事给整个网站目录chmod 777,结果第二天就被扫描器盯上,上传了恶意脚本;还有人把SSH私钥文件设成644,OpenSSH直接拒绝加载,报错Permissions are too open。这些都不是偶然错误,而是对权限模型理解断层的必然结果。本文不讲抽象理论,只拆解你每天真实会碰到的场景:为什么755是目录的黄金标准?为什么脚本文件必须加x位才能执行?umask到底是怎么悄悄改写你的新建文件权限?setuid和sticky bit在什么生死关头能救命?我会用真实终端录屏级的操作还原、参数推演过程、以及踩坑十年攒下的七条铁律——所有内容,你都可以立刻在自己的终端里验证、复现、修正。
2. 权限设计底层逻辑:为什么非得是“用户-组-其他”三层结构?
2.1 三层模型不是历史包袱,而是最小必要复杂度
很多人觉得“用户-组-其他”(User-Group-Others,简称UGO)这套权限体系过时了,不如ACL(访问控制列表)灵活,更比不上SELinux的多级安全策略。这话没错,但错在混淆了“适用场景”和“基础能力”。UGO权限是POSIX标准强制要求的基石,就像TCP/IP协议栈里的IP层——你可以用HTTP/HTTPS构建更复杂的交互,但底层数据包依然得靠IP地址路由。所有现代类Unix系统(Linux、macOS、FreeBSD)的文件系统(ext4、APFS、ZFS)都把UGO权限固化在inode元数据中,每次open()、stat()、execve()系统调用都会实时校验这9个比特位。
提示:
ls -l输出最左侧的10个字符中,第1位是文件类型(-普通文件、d目录、l符号链接等),后面9位就是UGO权限。例如drwxr-xr-x表示:目录(d)、所有者可读可写可执行(rwx)、所属组可读可执行(r-x)、其他人可读可执行(r-x)。
为什么偏偏是“三层”,而不是两层(owner/others)或四层(owner/group/others/admin)?答案藏在早期Unix的设计哲学里:用最少的抽象解决80%的协作问题。假设你在一个开发团队工作:
- 你是项目负责人,需要完全控制所有源码(owner)
- 同组5个后端工程师需要修改代码、编译二进制(group)
- 前端同事只需要读取API文档和接口定义(others)
这时,UGO刚好覆盖全部需求:你设chmod 664 *.py,自己和组员都能改,前端只能看。如果强行砍成两层,要么前端也能改代码(不安全),要么你得给每人单独建用户并重复授权(不可维护);如果扩展到四层,光是管理“admin”组的成员列表和同步成本,就远超实际收益。我参与过的某跨平台系统部署中,曾尝试用ACL给不同角色(dev/test/prod)分配细粒度权限,结果CI流水线因ACL继承规则混乱频繁失败,最终退回UGO+合理分组策略,稳定性提升3倍。
2.2 权限位的本质:三个独立的布尔开关组合
很多人误以为rwx是一个整体概念,其实它们是三个完全独立的比特位(bit),分别对应:
- r(read):对文件 = 可读取内容;对目录 = 可列出其中文件名(
ls) - w(write):对文件 = 可修改内容;对目录 = 可创建/删除/重命名该目录下的文件(注意:删除文件的权限由父目录的w位决定,而非文件自身!)
- x(execute):对文件 = 可作为程序执行(
./script.sh);对目录 = 可进入该目录(cd),并访问其下文件的元数据(stat子文件)
关键点来了:目录的x位常被严重低估。试想一个目录权限是r-w-(即600):
- 你能
ls它吗?不能,因为缺少x位,无法进入目录 - 你能
cat dir/file.txt吗?不能,因为路径解析需要先cd进dir,再找file.txt - 但如果你知道完整路径,且文件本身有r权限,
cat /full/path/to/dir/file.txt却可能成功——因为内核允许通过绝对路径绕过目录x检查(仅限root或特定capabilites)
我实测过这个场景:在某嵌入式设备调试中,客户误将日志目录设为700(即rwx------),导致监控脚本无法ls /var/log/app/获取最新日志名,但cat /var/log/app/latest.log仍能读取。最后解决方案不是开x位(会暴露目录结构),而是让脚本直接读固定文件名,避开目录遍历。
2.3 数字权限的计算逻辑:不是魔法,是二进制加法
755、644这些数字权限常让人困惑。其实它们是八进制表示法,每位对应一组rwx:
- r = 4, w = 2, x = 1 → rwx = 4+2+1 = 7, r-x = 4+0+1 = 5, rw- = 4+2+0 = 6
- 所以
755= owner:rwx(7) + group:rx(5) + others:rx(5) 644= owner:rw-(6) + group:r--(4) + others:r--(4)
为什么用八进制?因为3个比特位(rwx)正好组成一个八进制数(0-7),比二进制(000-111)易读,又比十进制(0-7)无歧义。当年Unix开发者选八进制,纯粹因为PDP-11处理器的寄存器宽度是12位(可被3整除),八进制天然契合硬件。
注意:
chmod 777不等于“完全开放”。它只是给了所有用户rwx,但若文件系统挂载时用了noexec选项(常见于/tmp分区),x位会被内核忽略;同样,nosuid选项会让setuid位失效。权限是“用户态请求+内核态校验”的双重门禁。
3. 核心权限场景深度拆解:从日常操作到生产陷阱
3.1 目录权限的黄金法则:755 vs 775 vs 777 的生死线
新手最容易犯的错,就是对目录权限“一刀切”。比如看到网站根目录/var/www/html是755,就认为所有目录都该如此。但实际要分三类场景:
场景A:公共可读目录(如Web根目录、共享文档库)
- 推荐权限:
755(drwxr-xr-x) - 逻辑:owner可管理(rwx),group和其他人只需浏览(r-x),禁止写入防止恶意篡改
- 实操验证:
mkdir testweb && chmod 755 testweb && touch testweb/index.html && ls -ld testweb应显示drwxr-xr-x - 风险点:若误设
777,攻击者可上传PHP木马并直接访问执行。某次某公司官网被黑,根源就是运维为方便FTP上传,把整个/var/www设为777
场景B:团队协作开发目录(如Git仓库工作区)
- 推荐权限:
775(drwxrwxr-x) - 逻辑:owner和group成员(开发组)都有完全控制权(rwx),others仅可读(r-x),避免外部人员误操作
- 关键配置:必须配合
setgid位(chmod g+s dirname),确保新创建文件自动继承父目录的group,否则组员创建的文件group仍是个人默认组,协作立即中断 - 我的实操心得:在某图像处理Demo项目中,我们用
chmod 2775 /project(2= setgid),然后所有组员usermod -aG dev username,从此git clone出来的文件group自动是dev,make build生成的二进制文件无需额外chown
场景C:绝对私有目录(如SSH密钥、数据库凭证)
- 推荐权限:
700(drwx------) - 逻辑:仅owner可读写执行,彻底隔绝其他所有用户
- 强制校验:OpenSSH启动时会检查
~/.ssh/id_rsa权限,若大于600(如644)则拒绝加载,并报错UNPROTECTED PRIVATE KEY FILE!。这不是警告,是硬性拒绝。
提示:用
namei -l /path/to/file可逐级检查路径中每个组件的权限。例如namei -l ~/.ssh/id_rsa会显示/→home→username→.ssh→id_rsa每一级的owner/group/perm,快速定位是哪一级目录权限过宽导致失败。
3.2 文件执行权限的隐秘规则:为什么脚本要chmod +x?
很多初学者写完Python脚本hello.py,直接python hello.py能跑,就以为不需要执行权限。但当你尝试./hello.py时,系统会报错Permission denied。原因在于两种执行路径的权限校验逻辑完全不同:
python hello.py:shell调用python解释器进程,解释器自己open()读取hello.py内容,此时只校验hello.py的读权限(r)./hello.py:shell尝试将hello.py作为独立程序执行,内核会检查hello.py的执行权限(x),且必须满足:- 文件有x位(
chmod +x hello.py) - 文件有shebang行(
#!/usr/bin/env python3),告诉内核用哪个解释器 - 解释器路径存在且可执行(
/usr/bin/env必须有x位)
- 文件有x位(
我曾帮某导师调试一个自动化评分脚本,学生交的grade.py总是./grade.py失败。检查发现:脚本首行是# python3(缺!),且权限是644。修复步骤三步:
sed -i '1s/^/#\!/' grade.py补全shebangchmod +x grade.py./grade.py成功执行
注意:Windows用户用Git Bash或WSL时,新建文件默认无x位,因为NTFS不原生支持Unix权限。此时需手动
chmod +x,否则CI流水线(Linux环境)必然失败。
3.3 umask:那个默默改写你新建文件权限的“幕后推手”
当你touch newfile或mkdir newdir,创建的文件权限不是随意定的,而是由umask(掩码)动态计算得出。公式很简单:
新建文件默认权限 = 666 & (~umask) 新建目录默认权限 = 777 & (~umask)其中&是按位与,~是按位取反。例如umask 022:
- 文件:
666 & ~022 = 666 & 755 = 644(rw-r--r--) - 目录:
777 & ~022 = 777 & 755 = 755(rwxr-xr-x)
umask的值通常在/etc/profile、~/.bashrc中设置。常见值:
022(最常用):平衡安全与便利,文件644/目录755002:适合开发组,文件664/目录775,新文件自动继承group写权限077:极致私有,文件600/目录700,所有新建内容仅owner可见
我在某公司做安全审计时发现,运维脚本/opt/scripts/backup.sh权限是600,但每次crontab执行后生成的备份文件却是644。追查发现:crond进程以root身份运行,其umask是系统默认022,而脚本本身权限不影响子进程umask。解决方案不是改脚本权限,而是在脚本开头显式设置umask 077,确保所有衍生文件都私有。
3.4 特殊权限位:setuid/setgid/sticky bit 的实战价值
除了常规rwx,还有三个特殊位,位于ugo权限的“高三位”(ls -l显示为s或t):
| 特殊位 | 位置 | 文件效果 | 目录效果 | 典型案例 |
|---|---|---|---|---|
| setuid (s) | owner的x位 | 执行时进程有效UID=文件owner | 无效果 | /usr/bin/passwd(普通用户执行时能修改/etc/shadow) |
| setgid (s) | group的x位 | 执行时进程有效GID=文件group | 新建文件自动继承目录group | /usr/bin/write(邮件发送时继承tty组) |
| sticky bit (t) | others的x位 | 无效果 | 文件只能由owner/目录owner/root删除 | /tmp(所有人可写,但只能删自己文件) |
setuid的真实风险与管控:/usr/bin/sudo就是setuid root的经典例子。但滥用setuid极其危险——任何有setuid位的可执行文件,一旦存在缓冲区溢出漏洞,攻击者就能获得owner权限(通常是root)。因此生产环境应严格审计:find / -perm -4000 2>/dev/null列出所有setuid文件,只保留系统必需项(passwd, sudo, mount等),其余一律移除。
sticky bit的救命场景:
某次某实验室的共享服务器,学生A在/shared/project下创建了build/目录并设777,学生B误删了A的编译产物。后来我们启用sticky bit:chmod 1777 /shared/project(1=sticky),此后即使目录全开放,B也无法删除A创建的文件,除非B是A、目录owner或root。ls -ld /shared/project显示drwxrwxrwt,末尾的t就是sticky bit生效的标志。
4. 实操全流程:从权限诊断到精准修复的七步法
4.1 第一步:用ls -l和stat看清真相
别猜,先看。ls -l是权限诊断的第一把刀,但很多人只看前10位,忽略关键信息:
$ ls -l /etc/passwd -rw-r--r-- 1 root root 2712 Apr 10 15:22 /etc/passwd # 字段分解: # 1. 权限位:-rw-r--r-- # 2. 硬链接数:1(对文件是链接数,对目录是子目录数+2) # 3. owner:root # 4. group:root # 5. 文件大小:2712字节 # 6. 修改时间:Apr 10 15:22 # 7. 文件名:/etc/passwd更精准的工具是stat,它显示inode级元数据:
$ stat /etc/passwd File: /etc/passwd Size: 2712 Blocks: 8 IO Block: 4096 regular file Device: 802h/2050d Inode: 131073 Links: 1 Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2024-04-10 15:22:33.123456789 +0000 Modify: 2024-04-10 15:22:33.123456789 +0000 Change: 2024-04-10 15:22:33.123456789 +0000 Birth: -注意(0644/-rw-r--r--)这一行,括号内是八进制权限,后面是符号化表示,双重确认。
4.2 第二步:用namei逐级追溯路径权限
当cd /a/b/c/d失败时,问题可能不在d,而在/a、/a/b或/a/b/c的任意一级。namei -l /a/b/c/d会像剥洋葱一样显示每一级的权限:
$ namei -l /var/log/apache2/access.log f: /var/log/apache2/access.log dr-xr-xr-x root root / drwxr-xr-x root root var drwxr-x--- root syslog log drwxr-s--- root www-data apache2 -rw-r----- root www-data access.log这里清晰看到:/var/log/apache2/权限是750(drwxr-s---),group是www-data,所以只有root和www-data组成员能进入;而access.log是640,只有root和www-data可读。如果普通用户想查看,需sudo cat access.log或被加入www-data组。
4.3 第三步:用getfacl和setfacl应对复杂需求
当UGO不够用时(如需给特定用户单独授权),ACL是标准方案。先检查是否启用:
$ mount | grep " $(df . | tail -1 | awk '{print $1}') " /dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro) # 若输出含 `acl`,则已启用;否则需重新挂载:mount -o remount,acl /典型ACL操作:
- 查看:
getfacl filename - 给用户bob读权限:
setfacl -m u:bob:r filename - 给组dev写权限:
setfacl -m g:dev:w filename - 删除bob权限:
setfacl -x u:bob filename - 清空所有ACL:
setfacl -b filename
注意:ACL会覆盖UGO权限,但ls -l只显示UGO部分,末尾加+表示存在ACL(如-rw-r--r--+)。真正查看需getfacl。
4.4 第四步:用find批量修复权限
线上环境常需批量修正权限。记住两个黄金命令:
修复所有目录为755,文件为644:
# 先测试(-print显示匹配项,不修改) find /path -type d -print find /path -type f -print # 确认无误后执行 find /path -type d -exec chmod 755 {} \; find /path -type f -exec chmod 644 {} \;修复Web目录:目录755,PHP文件755(需执行),HTML/CSS/JS文件644(只读):
find /var/www -type d -exec chmod 755 {} \; find /var/www -name "*.php" -exec chmod 755 {} \; find /var/www \( -name "*.html" -o -name "*.css" -o -name "*.js" \) -exec chmod 644 {} \;实操心得:永远先用
-exec。我曾因少打一个空格,find / -name "*.log" -exec rm {} \;变成find / -name "*.log" -exec rm {} \;(rm后无空格),结果rm命令没执行,但find耗尽CPU。加
4.5 第五步:用strace抓取权限拒绝的瞬间
当某个程序报Permission denied却找不到具体文件时,strace是终极武器。它跟踪系统调用,精确到哪一行代码、哪个open()调用失败:
# 跟踪nginx启动时的权限问题 strace -e trace=openat,open,stat -f nginx -t 2>&1 | grep "EACCES\|Permission" # 输出类似: openat(AT_FDCWD, "/etc/nginx/nginx.conf", O_RDONLY) = -1 EACCES (Permission denied)这行输出明确告诉你:nginx试图以只读方式打开/etc/nginx/nginx.conf,但被拒绝(EACCES)。此时检查该文件权限和父目录即可。
4.6 第六步:用auditd进行长期权限审计
对于生产服务器,需持续监控敏感权限变更。Linux audit subsystem可记录所有chmod/chown操作:
# 开启audit规则,监控/etc/目录下所有权限变更 auditctl -w /etc/ -p wa -k etc_permissions # 查看最近10条相关日志 ausearch -k etc_permissions | tail -10 # 日志示例: type=SYSCALL msg=audit(1712764800.123:456): arch=c000003e syscall=268 success=yes ... comm="chmod" exe="/usr/bin/chmod" ... cwd="/root" # 表明用户root在/root目录下执行了chmod命令这条规则会记录所有对/etc/的写(w)和属性修改(a)操作,关键词etc_permissions便于后续检索。
4.7 第七步:建立权限基线并自动化巡检
手工检查不可持续。我为某公司设计的权限巡检脚本核心逻辑如下:
#!/bin/bash # check_perms.sh CRITICAL_DIRS=("/etc" "/usr/bin" "/var/log") for dir in "${CRITICAL_DIRS[@]}"; do # 检查目录权限是否为755 if [ "$(stat -c "%a" "$dir" 2>/dev/null)" != "755" ]; then echo "ALERT: $dir permissions wrong: $(stat -c "%a" "$dir")" fi # 检查是否存在world-writable文件 if find "$dir" -type f -perm -002 -print | head -1 >/dev/null; then echo "ALERT: world-writable files in $dir" fi done配合cron每日执行:0 2 * * * /opt/scripts/check_perms.sh >> /var/log/perms_audit.log 2>&1。三年来,该脚本提前发现17次权限配置漂移,避免了潜在安全事件。
5. 常见问题与独家避坑指南:那些文档里不会写的血泪教训
5.1 “Permission denied” 但权限看起来完全正确?检查这五个隐藏点
问题现象:ls -l script.sh显示-rwxr-xr-x 1 user user 123 Apr 10 10:00 script.sh,./script.sh却报Permission denied。
排查清单(按优先级排序):
| 检查项 | 命令 | 说明 | 典型案例 |
|---|---|---|---|
| 1. 文件系统挂载选项 | mount | grep "$(df . | tail -1 | awk '{print $1}')" | 若含noexec,x位被忽略 | /tmp分区常挂载为noexec,nosuid,防止恶意代码执行 |
| 2. SELinux/AppArmor状态 | sestatus或aa-status | 强制访问控制策略可能覆盖UGO | RHEL/CentOS默认启用SELinux,ls -Z script.sh可看安全上下文 |
| 3. 文件是否被锁定 | lsof +D /path/to/dir | 进程正占用文件,内核可能拒绝执行 | 数据库日志文件被mysqld锁定时,chmod可能失败 |
| 4. 磁盘配额超限 | quota -u $USER | 用户配额满,无法写入inode | 某高校实验室学生账号配额1GB,touch新文件失败 |
| 5. 文件系统损坏 | dmesg | tail -20 | 内核日志报EXT4-fs error | 突然断电后ext4文件系统元数据损坏,权限位读取异常 |
我处理过最诡异的一次:某嵌入式设备上,/usr/local/bin/myapp权限755,./myapp报Permission denied。strace显示openat(..., O_RDONLY)成功,但execve()失败。最终发现是ARM平台的CONFIG_ARM64_UAO内核配置未启用,导致用户空间地址访问异常,与权限无关。这提醒我们:权限问题有时是底层硬件/内核的锅。
5.2 chmod递归操作的三大死亡陷阱
chmod -R是高效利器,也是事故高发区。务必牢记:
陷阱1:递归修改目录时,文件权限被错误应用chmod -R 755 /path会把所有文件(包括文本、图片)都设为755,导致cat image.jpg可能失败(jpg文件不需要x位)。正确做法:分开处理目录和文件:
find /path -type d -exec chmod 755 {} \; find /path -type f -exec chmod 644 {} \;陷阱2:符号链接被跟随(-H)或忽略(-L)的歧义chmod -R 755 symlink/默认不修改符号链接本身,而是修改它指向的目标。若想修改链接文件的权限(即链接文件自身的rwx),需加-h参数:chmod -h 755 symlink。
陷阱3:权限继承丢失chmod -R不会重置setgid位。若父目录有2755(setgid),chmod -R 755后变成755,新创建文件不再自动继承group。修复:chmod -R g+s /path。
我的血泪教训:某次为赶工期,对整个
/var/www执行chmod -R 777,结果不仅开了所有文件的x位,还清除了所有目录的setgid位。三天后新同事提交的PHP文件group变成他的个人组,Apache(运行在www-data组)无法读取,网站全白屏。恢复花了2小时——先chmod -R 755 /var/www,再chmod -R g+s /var/www,最后chgrp -R www-data /var/www。
5.3 SSH密钥权限的“零容忍”原则
OpenSSH对私钥权限执行最严格的校验:必须且仅能是600(rw-------)。任何偏差都会拒绝加载:
644→Permissions are too open640→Permissions are too open(others位为0,但group有r,仍视为不安全)600→ 正常加载400→ 正常加载(r--------,虽然少见,但符合“仅owner可读”)
修复命令:
chmod 600 ~/.ssh/id_rsa chmod 700 ~/.ssh # SSH目录也必须是700更隐蔽的问题:.ssh目录的父目录(如/home/user)若权限是777,某些OpenSSH版本也会警告。因此完整加固:
chmod 700 ~/.ssh chmod 600 ~/.ssh/id_rsa chmod 644 ~/.ssh/id_rsa.pub chmod 644 ~/.ssh/known_hosts chmod 644 ~/.ssh/config5.4 Docker容器内的权限迷思:为什么宿主机chmod无效?
在Docker中,docker run -v /host/path:/container/path ubuntu chmod 755 /container/path常失败。原因有三:
- 挂载时权限已固化:
-v挂载的目录,其权限由宿主机决定,容器内chmod只影响容器层,重启后丢失。 - 用户ID映射错位:宿主机user ID 1001,在容器内可能映射为nobody(65534),导致权限校验失败。
- rootless模式限制:Docker Desktop的rootless模式,容器内root用户实际是宿主机普通用户,无法修改宿主机文件权限。
解决方案:
- 最佳实践:在Dockerfile中用
RUN chmod设置镜像内文件权限,而非运行时修改挂载卷 - 临时方案:用
docker run -u $(id -u):$(id -g)强制容器内用户ID与宿主机一致 - 终极方案:用
bind mount的:z或:Z标签(SELinux)或:U(user namespace)自动处理权限
5.5 macOS上的特殊考量:ACL与Finder的权限冲突
macOS基于BSD,但增加了Apple专属的ACL扩展。ls -le可查看:
$ ls -le /Users/Shared drwxrwxrwt+ 5 root wheel 160 Apr 10 10:00 /Users/Shared 0: group:everyone deny delete这里的+表示存在ACL,deny delete规则阻止所有人删除文件(即使目录是777)。Finder界面修改权限时,会同时更新UGO和ACL,而命令行chmod只改UGO,导致不一致。
修复方法:
- 彻底清除ACL:
chmod -N /path/to/dir - 同步ACL与UGO:
chmod -E /path/to/dir(仅macOS)
我帮某导师处理过:他用Finder把共享目录设为“读与写”给所有人,但学生用终端touch /Users/Shared/test仍失败。ls -le发现ACL中有deny write规则。执行chmod -N /Users/Shared后,问题消失。
6. 权限管理的七条铁律:来自十年一线运维的终极总结
最小权限原则不是口号,是每行chmod的起点
创建文件/目录前,先问:谁真的需要写?谁只需要读?谁完全不该碰?宁可后续chmod g+w,也不要开局chmod 777。某次某公司因/tmp目录被设为1777(sticky bit正确),但内部子目录误设777,导致攻击者在/tmp/subdir放恶意so库,LD_PRELOAD劫持了root进程。目录的x位比文件的x位更重要
没有目录x位,你连ls都做不到。检查权限时,永远先cd进父目录,再操作子项。我习惯在~/.bashrc里加别名:alias cdls='cd "$1" && ls -la',一步到位。umask是团队协作的隐形契约
开发组统一设umask 002,比每次chmod g+w更可靠。把它写进团队Wiki,新成员入职第一件事就是配置。setuid/setgid是双刃剑,不用则已,用必审计
find / -perm -4000 -o -perm -2000 2>/dev/null每月执行一次,结果邮件发给安全组。某次扫描发现/usr/bin/screen有setuid,但它是合法的(用于多用户会话共享),确认后加入白名单。符号链接的权限毫无意义,只看目标
ls -l symlink显示的权限