这个命令是干啥的
Linux是个多用户系统,每个文件和目录都有对应的主人和权限设置。chmod 和 chown 就是用来管这个的。
chown 改文件的主人是谁,chmod 改文件谁能干什么。
我刚学Linux的时候,遇到权限问题就一招:chmod 777。不管什么文件,直接给所有人全部权限。结果被老运维骂了一顿。后来生产环境有一次数据库配置文件被我设成了777,安全扫描直接报警,吓得我赶紧改了。
权限问题不能靠蛮力,得理解背后的原理。
基本用法(3分钟上手)
文件权限长啥样
先看一个文件的权限位:
# 查看文件权限
ls -l filename
# 输出示例
-rwxr-xr-- 1 root root 1234 Jan 15 10:00 filename
拆开看:
- 第1个字符:- 表示文件,d 表示目录
- 接着3个一组:主人(u) - 用户组(g) - 其他人(o)
- rwx = 读(4) 写(2) 执行(1)
上面这个例子:
- 主人(root)有 rwx 全部权限
- 组里的用户有 r-x (读和执行)
- 其他人只有 r-- (只能读)
chmod 数字法
权限可以用数字表示:r=4, w=2, x=1
# 754: 主人rwx(7), 组rx(5), 其他人r(4)
chmod 754 filename
# 755: 常见于目录和脚本
chmod 755 script.sh
# 644: 常见于普通文件
chmod 644 readme.txt
chmod 符号法
不喜欢数字可以用字母:
# 给主人加执行权限
chmod u+x script.sh
# 取消组和其他人的执行权限
chmod go-x script.sh
# 给所有人加读权限
chmod a+r config.txt
# 给主人加rw,其他只读
chmod u=rw,go=r file.txt
chown 改主人
# 把文件的主人改成 zhangsan
sudo chown zhangsan file.txt
# 同时改主人和组
sudo chown zhangsan:devops file.txt
# 只改组,不改主人
sudo chown :devops file.txt
# 也可以这么写
sudo chgrp devops file.txt
递归处理目录
# 递归改目录及其内部所有文件的权限
chmod -R 755 /var/www/html
# 递归改目录及其内部所有文件的主人
sudo chown -R www-data:www-data /var/www/html
进阶骚操作
SUID 特殊位
SUID 的意思是:谁执行这个文件,就临时获得文件主人的权限。最典型的例子是 passwd 命令:
# 查看 passwd 命令的权限
ls -l /usr/bin/passwd
# 输出里有个 s 在主人执行位
-rwsr-xr-x 1 root root 68208 ...
那个 s 就是 SUID。普通用户执行 passwd 改密码时,借着 SUID 以 root 身份修改 /etc/shadow 文件。
# 给文件设置SUID
chmod u+s /path/to/program
# 或者用数字法(在权限前加4)
chmod 4755 /path/to/program
SGID 特殊位
SGID 设到目录上时,在这个目录里新建的文件会自动继承目录的组,而不是创建者自己的组。做项目共享目录时很有用。
# 设置SGID
chmod g+s /shared/project
# 数字法:权限前加2
chmod 2775 /shared/project
粘滞位(Sticky Bit)
/tmp 目录就是典型例子:任何人都能往里面写文件,但谁的文件只能谁删。粘滞位在其他人的执行位上显示为 t。
# 查看 /tmp 的权限
ls -ld /tmp
# 输出:drwxrwxrwt ... 最后的 t 就是粘滞位
# 给目录设置粘滞位
chmod +t /shared/uploads
# 数字法:权限前加1
chmod 1777 /shared/uploads
特殊权限组合
特殊位的数字是叠加的:SUID(4) + SGID(2) + Sticky(1)
# SUID + SGID + Sticky,权限为777
chmod 7777 dangerous.sh
# 但别这么干,非常危险
实际常用的组合:
# SUID + rwxr-xr-x
chmod 4755 suid-program
# SGID + rwxrwsr-x (目录共享)
chmod 2775 /shared
# Sticky + rwxrwxrwt (公共目录)
chmod 1777 /tmp
避坑指南
坑1:chmod 777 的危害
chmod 777 等于对全世界说:随便看随便改随便执行。后果:
- ·任何人都能读你的配置文件(数据库密码泄漏)
- ·任何人都能修改你的脚本(被别人植入恶意代码)
- ·任何人都能执行你的程序(被用来干坏事)
正确的做法:给最小的必要权限。 文件就644或600,目录就755或700。
我有一台测试服务器图省事,把 /var/www 设成了777,结果被人上传了挖矿脚本,CPU一直100%。
坑2:chown -R 改到系统目录
有次手滑:
# 手滑写错了路径
sudo chown -R myuser:myuser / usr/lib
# 注意 / 后面多了空格!
好在发现得早,赶紧 Ctrl+C 了。要是没发现,整个系统的文件主人全改了,系统直接废掉。
建议: 用 chown -R 的时候,先 echo 一下路径确认。
坑3:SUID 对脚本不生效
SUID 对二进制程序管用,但对shell脚本、Python脚本基本没用。很多Linux发行版出于安全考虑,会忽略脚本的SUID。
不依赖SUID,用 sudo 配合 /etc/sudoers 配置更靠谱。
坑4:执行权限和目录的关系
很多人搞不清:目录的 x 权限代表啥?
- ·目录的
r:能看到目录里的文件名(ls) - ·目录的
x:能进入目录(cd),能访问里面的文件 - ·目录的
w:能在目录里增删文件
所以目录至少需要 rx 才能正常访问内容。只给 r 不给 x,你能 ls 文件名,但 cd 进去会报错。
实战场景(重点!结合真实运维场景)
场景1:部署Web项目
最经典的场景,Nginx/PHP网站部署:
# 项目目录交给 www-data 用户
sudo chown -R www-data:www-data /var/www/myapp
# 文件权限 644
find /var/www/myapp -type f -exec chmod 644 {} \;
# 目录权限 755
find /var/www/myapp -type d -exec chmod 755 {} \;
# 上传目录要能写入
chmod -R 775 /var/www/myapp/uploads
这样文件只能主人改,别人只能看,安全多了。
场景2:多用户协作目录
团队用同一个服务器,需要共享工作目录:
# 创建共享目录
sudo mkdir -p /data/shared
# 改组为 devops
sudo chgrp -R devops /data/shared
# 设权限:主人rwx,组rwx,其他人无权限
sudo chmod -R 770 /data/shared
# SGID:新文件自动继承组
sudo chmod g+s /data/shared
这样所有 devops 组的成员都能读写共享目录,外面的人进不来。
场景3:安全加固脚本
新服务器上线前做的权限加固:
#!/bin/bash
# 生产环境权限加固
echo "开始权限加固..."
# SSH配置只能主人读写
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 700 ~/.ssh
# 敏感配置文件
chmod 600 /etc/shadow
chmod 644 /etc/passwd
chmod 600 /etc/ssh/sshd_config
# 日志目录
chmod 750 /var/log
find /var/log -type f -exec chmod 640 {} \;
echo "权限加固完成"
场景4:权限问题排查
当程序报"Permission denied"时:
# 先看文件主人和权限
ls -la /path/to/problem-file
# 看当前是谁在跑
whoami
id
# 看目录权限(经常是目录的x权限不够)
namei -l /path/to/problem-file
# 临时提权测试
sudo -u www-data ls -la /path/to/problem-file
namei 这个命令能列出路径上每一级的权限,方便定位卡在哪一层。
今日作业
1. 创建测试目录:mkdir -p /tmp/test-perm && cd /tmp/test-perm
2. 创建文件 touch secret.txt config.txt
3. 把 secret.txt 权限设为600(只有你自己能读写)
4. 把 config.txt 权限设为644(你自己读写,别人只能读)
5. 创建一个 bin 子目录,权限设为700(只有你能进入)
6. 在 bin 里放一个脚本 test.sh,给主人加执行权限
完成后,用 ls -laR 查看整个目录结构,检查权限是否符合预期。