背景与目的
Linux权限体系是运维工作的基础中的基础。无论你管理的是单机还是集群,权限问题导致的故障占总故障量的相当比例。本文从一线运维视角出发,系统讲解Linux权限模型的核心概念、常见场景、排障方法以及安全最佳实践。阅读本文后,你应该能够独立处理90%以上的权限相关问题。
前置知识:本文假设你已经掌握Linux基本操作,包括文件导航、查看目录内容等基础命令。
环境说明:本文所有示例基于Rocky Linux 9.4(等同于RHEL 9.4),内核版本6.8.5,GNU Coreutils 9.1。不同发行版细节可能略有差异,但核心原理一致。
1. Linux权限体系概述
1.1 为什么运维必须掌握权限
权限问题是Linux系统中最常见的故障来源之一。根据实际运维统计,约30%的文件访问故障、20%的服务启动失败、15%的安全事件都与权限配置不当有直接关系。权限管理不当会导致以下典型问题:
服务无法启动:Web服务(如Nginx、Apache)通常以特定用户(如www-data、nginx)运行,如果网站文件权限不允许该用户读取,服务启动后会返回403错误。
日志无法写入:应用程序的日志文件需要由运行该程序的用户写入,如果目录权限不足,日志会写入失败或产生大量错误。
备份脚本失效:自动化备份脚本通常以root权限运行,但备份的目标目录如果权限配置异常,可能导致备份不完整。
安全漏洞:权限配置过于宽松(如文件设为777)会被安全扫描工具标记为高危漏洞,严重情况下可能导致服务器被入侵。
1.2 Linux权限模型的基本组成
Linux采用UGO(User/Group/Others)三元组的权限控制模型。每个文件(目录也是文件)都有三组权限位:
Owner(所有者):文件所属的用户,U位控制
Group(所属组):文件所属的用户组,G位控制
Others(其他人):既不是所有者也不属于所属组的其他用户,O位控制
每组权限包含三种基本权限:
r(Read):读取权限,数值4
w(Write):写入权限,数值2
x(Execute):执行权限,数值1
这种设计简洁高效,三位二进制正好对应rwx三种状态。例如,rwx用数字表示就是4+2+1=7,rw-就是4+2=6,r--就是4。
2. 基本权限模型详解
2.1 查看文件权限
使用ls -l命令可以查看文件的详细权限信息:
$ ls -l /etc/passwd -rw-r--r-- 1 root root 4096 Apr 3 10:00 /etc/passwd $ ls -ld /tmp drwxrwxrwt 15 root root 4096 Apr 3 10:00 /tmp
第一列是权限字符串,共10位:
- rw- r-- r-- | | | | | | | +-- Others权限 | | +------ Group权限 | +---------- Owner权限 +-------------文件类型(-为普通文件,d为目录,l为符号链接)
权限字符串后是硬链接数,然后是所有者、所属组、文件大小、最后修改时间、文件名。
2.2 权限位数字表示法
每组权限可以用三位八进制数字表示,这是最常用的权限设置方式:
| 权限字符串 | 数字表示 | 计算方式 |
|---|---|---|
| rwx | 7 | 4+2+1 |
| rw- | 6 | 4+2+0 |
| r-x | 5 | 4+0+1 |
| r-- | 4 | 4+0+0 |
| -wx | 3 | 0+2+1 |
| -w- | 2 | 0+2+0 |
| --x | 1 | 0+0+1 |
| --- | 0 | 0+0+0 |
完整的三位权限表示法示例:
# rwxrw-r-- 用数字表示就是 764 # 第1位7:所有者权限为rwx # 第2位6:所属组权限为rw- # 第3位4:其他人权限为r-- chmod 764 /path/to/file
2.3 chmod命令详解
chmod是修改文件权限的核心命令,支持两种语法风格:
符号模式:使用u/g/o/a(user/group/others/all)和+/-/=操作符
# 给所有者添加执行权限 chmod u+x script.sh # 移除所属组和其他人的写权限 chmod go-w file.txt # 设置所有者为rwx,所属组为rx,其他人无权限 chmod u=rwx,g=rx,o= file.conf # 给所有人添加读权限 chmod a+r document.txt # 同时设置多组权限 chmod u+rwx,g+rx,o+r file
数字模式:使用八进制数字直接指定权限
# 设置为755(rwxr-xr-x) chmod 755 /usr/local/bin/app # 设置为644(rw-r--r--) chmod 644 /etc/config.conf # 设置为600(rw-------) chmod 600 /root/.ssh/id_rsa # 递归设置目录内所有文件 chmod -R 644 /var/www/html/
注意:使用-R递归时,默认只修改文件本身,不修改目录结构。如果需要同时修改目录和文件的权限,使用:
# 目录设为755,文件设为644
find /var/www -typed -execchmod 755 {} ;
find /var/www -typef -execchmod 644 {} ;
# 或使用GNU find的+速记
find /var/www -typed -print0 | xargs -0 chmod 755
find /var/www -typef -print0 | xargs -0 chmod 644
2.4 chown和chgrp命令
chown用于更改文件的所有者:
# 更改文件所有者 chown nginx /var/www/html/index.html # 同时更改所有者和所属组 chown nginx:nginx /var/www/html/index.html # 只更改所属组(使用:前缀) chown :www-data /var/www/html/index.html # 递归更改 chown -R nginx:nginx /var/www/html/ # 保持用户组不变,只改用户 chown nginx /var/www/html/index.html
chgrp用于只更改所属组:
# 更改文件所属组 chgrp www-data /var/www/html/index.html # 递归更改 chgrp -R www-data /var/www/html/
2.5 默认权限与umask
新建文件或目录时,系统会根据umask值计算出默认权限。普通文件的默认权限是666(rw-rw-rw-),目录的默认权限是777(rwxrwxrwx)。umask值会从默认权限中扣除。
# 查看当前umask $umask 0022 # 计算默认权限: # 文件:666 - 022 = 644 (rw-r--r--) # 目录:777 - 022 = 755 (rwxr-xr-x)
常见umask场景:
root用户默认umask为0022,普通文件权限644,目录755
普通用户默认umask为0002,组内成员可写,适合协作场景
# 修改umask(临时,只影响当前shell) umask0027 # 永久修改需要编辑~/.bashrc或/etc/profile echo"umask 0027">> ~/.bashrc source~/.bashrc
3. 特殊权限详解
除了基本的rwx权限,Linux还提供了三种特殊权限:SUID、SGID和Sticky Bit。它们在安全和服务配置中有重要应用。
3.1 SUID(Set User ID)
SUID位允许可执行文件在运行时使用文件所有者的权限执行,而不是调用者的权限。这在需要临时提升权限的场景中很有用,但也是常见的安全风险点。
设置SUID:
# 设置SUID chmod u+s /usr/bin/passwd # 数字方式设置(4表示SUID) chmod 4755 /usr/bin/passwd # 查看已设置SUID的文件 find /usr -perm +4000 -ls 2>/dev/null
典型应用:passwd命令
$ ls -l /usr/bin/passwd -rwsr-xr-x 1 root root 68208 Jan 31 2026 /usr/bin/passwd # ^ # 注意这个s替代了x,表示SUID已设置
普通用户修改自己的密码需要写入/etc/shadow,但普通用户没有写权限。passwd命令设置了SUID后,普通用户执行时会以root权限运行,从而能够修改shadow文件。
安全风险警示:
SUID是Linux中最危险的安全机制之一。错误地给Shell脚本设置SUID会导致严重漏洞,因为攻击者可能通过脚本获得root shell。
# 高危操作示例 - 绝对不要这样做
chmod 4777 /bin/bash # 危险!
# 查找系统中所有SUID文件用于安全审计
find / -perm +4000 -typef -execls -la {} ; 2>/dev/null
3.2 SGID(Set Group ID)
SGID与SUID类似,但作用于所属组。有两种用途:
在文件上设置SGID:执行时使用文件所属组的权限
在目录上设置SGID:目录下新建的文件继承该目录的所属组
# 在目录上设置SGID chmod g+s /shared/project # 查看目录SGID设置 $ ls -ld /shared/project drwxrwsr-x 2 root developers shared 4096 Apr 3 10:00 /shared/project # 验证:新建文件继承组 $ touch /shared/project/test.txt $ ls -l /shared/project/test.txt -rw-r--r-- 1 user1 developers 0 Apr 3 10:01 /shared/project/test.txt # ^^^^^^^^ # 继承了目录的所属组
数字方式设置SGID:
# 2表示SGID chmod 2775 /shared/project
3.3 Sticky Bit(粘滞位)
Sticky Bit主要用于共享目录,确保目录内的文件只能被其所有者删除,即使其他人有该目录的写权限。
# 设置Sticky Bit chmod +t /tmp # 或者数字方式(1表示Sticky Bit) chmod 1777 /tmp # 查看 $ ls -ld /tmp drwxrwxrwt 17 root root 4096 Apr 3 10:00 /tmp # ^ # 注意最后的t,t表示同时有x权限,T表示没有x权限
/tmp目录的典型权限:
# 1777 = rwx rwx rwx + t # 任何用户都可以在/tmp中创建文件 # 但只能删除自己的文件
实际验证:
# 用户A创建文件 $ su - userA $ touch /tmp/file_a.txt # 用户B尝试删除用户A的文件 $ su - userB $ rm /tmp/file_a.txt rm: cannot remove'/tmp/file_a.txt': Operation not permitted # 成功保护!
3.4 特殊权限组合示例
# 完整权限示例:rwsr-sr-x (SUID + SGID) # 数字表示:6755 chmod 6755 /some/executable # /tmp格式的目录:drwxrwxrwt # 数字表示:1777 chmod 1777 /my/temp/dir
4. ACL访问控制列表
传统的UGO权限模型在复杂场景下不够灵活。例如,需要让多个特定用户或组对同一文件有不同的权限时,UGO模型就无法满足。ACL(Access Control List)提供了细粒度的权限控制。
4.1 ACL查看:getfacl
# 查看文件的ACL $ getfacl /data/reports/sales.csv # file: sales.csv # owner: root # group: finance user::rw- userrw- group::r-- groupr-- mask::rw- other::r--
输出解释:
user::rw-:文件所有者权限
userrw-:特定用户manager的权限
group::r--:文件所属组权限
groupr--:特定组analytics的权限
mask::rw-:ACL有效权限掩码(后面详解)
other::r--:其他用户权限
4.2 ACL设置:setfacl
添加用户ACL:
# 给特定用户添加读权限 setfacl -m ur /path/to/file # 给特定用户添加读写执行权限 setfacl -m urwx /path/to/file # 设置用户的有效权限(不超过mask限制) setfacl -m urw /path/to/file
添加组ACL:
# 给特定组添加读权限 setfacl -m gr /path/to/file # 给特定组添加读写权限 setfacl -m grw /path/to/file
设置默认ACL(目录):
# 设置目录默认ACL,该目录下新建文件自动继承 setfacl -m dusername:rw /shared/folder/ # 查看默认ACL getfacl /shared/folder/
删除ACL:
# 删除特定用户的ACL setfacl -x u:username /path/to/file # 删除特定组的ACL setfacl -x g:groupname /path/to/file # 删除所有扩展ACL(恢复传统权限) setfacl -b /path/to/file
4.3 ACL掩码
ACL掩码(mask)限制了所有ACL条目的最大权限。mask中设置的权限决定了一切非所有者ACL条目的有效上限。
# 查看mask getfacl file | grep mask # 设置mask(所有ACL条目受此限制) setfacl -m m::rw /path/to/file
mask的作用:
# 如果mask是r--,即使设置urwx,实际生效也只有r-- # 这确保了ACL不会意外提升权限 $ setfacl -m urwx /shared.txt $ setfacl -m m::r-- /shared.txt $ getfacl /shared.txt userrwx #-effective:r-- # alice的有效权限被mask限制为r--
4.4 ACL权限继承
目录的默认ACL可以实现权限继承:
# 创建项目目录 mkdir -p /projects/webapp # 设置目录默认ACL(子目录和文件继承) setfacl -R -m ddeveloper:rwX /projects/webapp/ # 设置组的默认ACL setfacl -R -m ddevteam:rwX /projects/webapp/ # 验证继承效果 cd/projects/webapp touch test.txt mkdir subdir ls -la # 应该看到+号表示有ACL getfacl test.txt
4.5 ACL实用脚本
批量设置目录ACL:
#!/bin/bash
# script: batch_setfacl.sh
# 用途:批量为项目目录设置ACL权限
PROJECT_DIR="/projects"
DEVELOPER="developer"
DEVTEAM="devteam"
# 设置目录基础权限
chown -R${DEVELOPER}:${DEVTEAM}${PROJECT_DIR}
# 设置目录ACL继承
fordirin${PROJECT_DIR}/*/;do
echo"Setting ACL for:${dir}"
setfacl -R -m u:${DEVELOPER}:rwX"${dir}"
setfacl -R -m g:${DEVTEAM}:rwX"${dir}"
setfacl -R -m d${DEVELOPER}:rwX"${dir}"
setfacl -R -m d${DEVTEAM}:rwX"${dir}"
done
echo"ACL setup completed"
备份ACL权限:
#!/bin/bash
# script: backup_acl.sh
# 用途:备份指定目录的ACL权限到文件
BACKUP_DIR="/var/backup/acl"
TARGET_DIR="/home"
mkdir -p"${BACKUP_DIR}"
# 使用getfacl -R备份,-p选项去掉注释行
getfacl -R"${TARGET_DIR}"2>/dev/null >"${BACKUP_DIR}/acl_backup_$(date +%Y%m%d).txt"
echo"ACL backed up to${BACKUP_DIR}"
恢复ACL权限:
#!/bin/bash
# script: restore_acl.sh
# 用途:从备份恢复ACL权限
BACKUP_FILE="/var/backup/acl/acl_backup_20260403.txt"
if[ ! -f"${BACKUP_FILE}"];then
echo"Backup file not found!"
exit1
fi
# 使用setfacl --restore恢复
setfacl --restore="${BACKUP_FILE}"
echo"ACL restored successfully"
5. 文件属性
除了权限位,Linux还提供了文件属性(Attributes)机制,用于控制文件的其他行为。文件属性使用chattr和lsattr命令管理。
5.1 查看文件属性
# 使用lsattr查看 $ lsattr /etc/passwd -------------e-- /etc/passwd # 常用属性位说明: # e = extent format(扩展格式,ext4默认) # i = immutable(不可修改) # a = append only(只能追加) # d = no dump(dump备份时忽略) # s = secure deletion(安全删除)
5.2 设置不可修改属性
chattr +i:最常用的安全属性,设置后文件不能被删除、修改、重命名,连root也无法操作(除非先移除属性)。
# 保护重要配置文件 chattr +i /etc/passwd chattr +i /etc/shadow chattr +i /etc/group chattr +i /etc/gshadow # 验证保护效果 rm /etc/passwd rm: cannot remove'/etc/passwd': Operation not permitted # 取消保护 chattr -i /etc/passwd
典型应用场景:
#!/bin/bash
# script: protect_system_files.sh
# 用途:保护关键系统文件不被误删或篡改
PROTECTED_FILES=(
"/etc/passwd"
"/etc/shadow"
"/etc/group"
"/etc/gshadow"
"/etc/inittab"
"/etc/fstab"
)
forfilein"${PROTECTED_FILES[@]}";do
if[ -f"$file"];then
chattr +i"$file"2>/dev/null &&echo"Protected:$file"
fi
done
echo"System files protection completed"
5.3 设置追加属性
chattr +a:文件只能追加数据,不能删除或覆盖。适合日志文件和某些配置文件。
# 保护日志文件 chattr +a /var/log/messages chattr +a /var/log/secure # 添加日志内容 echo"new log entry">> /var/log/messages # 尝试覆盖(会失败) echo"overwrite"> /var/log/messages -bash: /var/log/messages: Operation not permitted # 取消追加属性 chattr -a /var/log/messages
5.4 组合使用属性
# 同时设置不可修改和追加属性 chattr +i /var/log/audit.log chattr +a /var/log/audit.log # 目录的属性设置 # +i对目录设置后,目录下不能新建或删除文件 mkdir /secure_dir chattr +i /secure_dir touch /secure_dir/test.txt touch: cannot touch'/secure_dir/test.txt': Permission denied
5.5 安全增强属性脚本
#!/bin/bash
# script: audit_file_attributes.sh
# 用途:审计文件属性变更,检测潜在安全事件
LOG_FILE="/var/log/attribute_audit.log"
MONITOR_DIRS=("/etc""/bin""/sbin""/usr/bin""/usr/sbin")
log_message() {
echo"[$(date '+%Y-%m-%d %H:%M:%S')]$1">>"${LOG_FILE}"
}
check_attributes() {
localdir="$1"
localflag_file="/tmp/attr_baseline_${dir////_}.txt"
# 如果没有基准文件,创建基准
if[ ! -f"${flag_file}"];then
lsattr -R"${dir}"2>/dev/null | grep'^[a-zA-Z-]*i'>"${flag_file}"
log_message"Created baseline for${dir}"
return
fi
# 检查变更
localcurrent_file="/tmp/attr_current_${dir////_}.txt"
lsattr -R"${dir}"2>/dev/null | grep'^[a-zA-Z-]*i'>"${current_file}"
if! diff -q"${flag_file}""${current_file}"> /dev/null 2>&1;then
log_message"ALERT: Immutable attribute changed in${dir}"
diff"${flag_file}""${current_file}">>"${LOG_FILE}"
fi
}
# 主循环
fordirin"${MONITOR_DIRS[@]}";do
if[ -d"$dir"];then
check_attributes"$dir"
fi
done
echo"Attribute audit completed"
6. 权限相关命令实战
6.1 权限检查脚本集合
检查可疑权限:
#!/bin/bash # script: check_suspicious_perms.sh # 用途:检查系统中权限配置异常的文件 REPORT="/tmp/permission_report_$(date +%Y%m%d).txt" echo"=== Permission Check Report ===">"${REPORT}" echo"Generated:$(date)">>"${REPORT}" echo"">>"${REPORT}" # 1. 检查777权限的文件 echo"=== Files with 777 permission ===">>"${REPORT}" find / -typef -perm 777 2>/dev/null >>"${REPORT}" echo"">>"${REPORT}" # 2. 检查SUID文件 echo"=== SUID Files ===">>"${REPORT}" find / -typef -perm +4000 2>/dev/null >>"${REPORT}" echo"">>"${REPORT}" # 3. 检查SGID文件 echo"=== SGID Files ===">>"${REPORT}" find / -typef -perm +2000 2>/dev/null >>"${REPORT}" echo"">>"${REPORT}" # 4. 检查无主文件(无有效所有者的文件) echo"=== Unowned Files ===">>"${REPORT}" find / -nouser -o -nogroup 2>/dev/null >>"${REPORT}" echo"">>"${REPORT}" # 5. 检查world-writable目录 echo"=== World-Writable Directories ===">>"${REPORT}" find / -typed -perm -002 2>/dev/null | grep -v'/proc'| grep -v'/sys'>>"${REPORT}" cat"${REPORT}" echo"" echo"Report saved to:${REPORT}"
修正常见权限问题:
#!/bin/bash
# script: fix_common_perms.sh
# 用途:修正常见的权限配置问题
set-e
echo"Starting permission fixes..."
# 1. 修正用户home目录权限
echo"Fixing home directory permissions..."
foruserin$(ls /home/);do
if[ -d"/home/$user"];then
chmod 700"/home/$user"
chown"$user:$user""/home/$user"
echo" Fixed: /home/$user"
fi
done
# 2. 修正SSH密钥权限
echo"Fixing SSH key permissions..."
if[ -d"/root/.ssh"];then
chmod 700 /root/.ssh
chmod 600 /root/.ssh/id_rsa
chmod 644 /root/.ssh/id_rsa.pub
chmod 600 /root/.ssh/authorized_keys
echo" Fixed: /root/.ssh"
fi
# 3. 修正系统日志目录权限
echo"Fixing log directory permissions..."
chmod 755 /var/log
chmod 755 /var/log/httpd 2>/dev/null ||true
chmod 755 /var/log/nginx 2>/dev/null ||true
# 4. 修正配置文件权限(保留读取权限但移除组和其他写权限)
echo"Fixing config file permissions..."
find /etc -typef -name"*.conf"-execchmod 644 {} ; 2>/dev/null
find /etc -typef -name"*.cfg"-execchmod 644 {} ; 2>/dev/null
echo"Permission fixes completed!"
6.2 Web服务权限配置
Nginx权限配置:
#!/bin/bash
# script: setup_nginx_perms.sh
# 用途:配置Web目录的标准权限
WEB_ROOT="/var/www/html"
NGINX_USER="nginx"
NGINX_GROUP="nginx"
echo"Setting up Nginx permissions..."
# 设置目录基础权限
chown -R${NGINX_USER}:${NGINX_GROUP}"${WEB_ROOT}"
# 目录设为755
find"${WEB_ROOT}"-typed -execchmod 755 {} ;
# 文件设为644
find"${WEB_ROOT}"-typef -execchmod 644 {} ;
# 上传目录单独处理
if[ -d"${WEB_ROOT}/uploads"];then
chown -R${NGINX_USER}:${NGINX_GROUP}"${WEB_ROOT}/uploads"
chmod 755"${WEB_ROOT}/uploads"
# 上传目录不放执行权限
find"${WEB_ROOT}/uploads"-typef -execchmod 644 {} ;
echo" Special handling for uploads directory"
fi
# 配置文件权限
chown root:root /etc/nginx/nginx.conf
chmod 644 /etc/nginx/nginx.conf
echo"Nginx permissions configured successfully"
PHP-FPM权限配置:
#!/bin/bash
# script: setup_phpfpm_perms.sh
# 用途:配置PHP-FPM与Web服务的协同权限
WEB_ROOT="/var/www/html"
PHP_USER="php-fpm"
PHP_GROUP="php-fpm"
NGINX_USER="nginx"
echo"Configuring PHP-FPM permissions..."
# PHP-FPM运行用户(/etc/php-fpm.d/www.conf)
# 确保Pool配置正确
sed -i"s/^user = .*/user =${PHP_USER}/"/etc/php-fpm.d/www.conf
sed -i"s/^group = .*/group =${PHP_GROUP}/"/etc/php-fpm.d/www.conf
# 设置Socket权限
SOCKET_FILE="/var/run/php-fpm/php-fpm.sock"
if[ -S"${SOCKET_FILE}"];then
chown${PHP_USER}:${NGINX_USER}"${SOCKET_FILE}"
chmod 660"${SOCKET_FILE}"
echo" Socket permissions configured"
fi
# Web目录权限
chown -R${PHP_USER}:${NGINX_USER}"${WEB_ROOT}"
find"${WEB_ROOT}"-typed -execchmod 755 {} ;
find"${WEB_ROOT}"-typef -execchmod 644 {} ;
# 缓存目录(PHP需要写权限)
fordirin"${WEB_ROOT}"/{cache,tmp,uploads};do
if[ -d"$dir"];then
chown -R${PHP_USER}:${NGINX_USER}"$dir"
chmod 755"$dir"
fi
done
echo"PHP-FPM permissions configured"
6.3 数据库权限配置
MySQL数据目录权限:
#!/bin/bash
# script: setup_mysql_perms.sh
# 用途:配置MySQL标准权限
MYSQL_USER="mysql"
MYSQL_GROUP="mysql"
MYSQL_DATA="/var/lib/mysql"
MYSQL_LOG="/var/log/mysql"
MYSQL_RUN="/var/run/mysql"
echo"Setting MySQL permissions..."
# 数据目录
chown -R${MYSQL_USER}:${MYSQL_GROUP}"${MYSQL_DATA}"
chmod 700"${MYSQL_DATA}"
# 日志目录
if[ -d"${MYSQL_LOG}"];then
chown -R${MYSQL_USER}:${MYSQL_GROUP}"${MYSQL_LOG}"
chmod 750"${MYSQL_LOG}"
fi
# Socket目录
if[ -d"${MYSQL_RUN}"];then
chown -R${MYSQL_USER}:${MYSQL_GROUP}"${MYSQL_RUN}"
chmod 755"${MYSQL_RUN}"
fi
# 配置文件
chown root:root /etc/my.cnf
chmod 644 /etc/my.cnf
echo"MySQL permissions configured"
PostgreSQL权限配置:
#!/bin/bash
# script: setup_postgres_perms.sh
# 用途:配置PostgreSQL标准权限
PSQL_USER="postgres"
PSQL_GROUP="postgres"
PSQL_DATA="/var/lib/pgsql/data"
PSQL_LOG="/var/log/postgresql"
echo"Setting PostgreSQL permissions..."
# 数据目录
chown -R${PSQL_USER}:${PSQL_GROUP}"${PSQL_DATA}"
chmod 700"${PSQL_DATA}"
# 只允许postgres用户访问
chmod 700"${PSQL_DATA}"
# HBA配置文件(认证配置)
chown${PSQL_USER}:${PSQL_GROUP}/var/lib/pgsql/data/pg_hba.conf
chmod 600 /var/lib/pgsql/data/pg_hba.conf
echo"PostgreSQL permissions configured"
6.4 备份权限处理
#!/bin/bash
# script: backup_with_perms.sh
# 用途:完整备份文件和目录及其权限
SOURCE_DIR="/data/app"
BACKUP_DIR="/backup/$(date +%Y%m%d_%H%M%S)"
TAR_FILE="${BACKUP_DIR}/backup.tar.gz"
echo"Starting backup with permissions..."
mkdir -p"${BACKUP_DIR}"
# 使用tar保留权限属性
tar -czpf"${TAR_FILE}"
--acls
--xattrs
--selinux
-C"$(dirname "${SOURCE_DIR}")""$(basename "${SOURCE_DIR}")"
# 创建权限信息文件
getfacl -R"${SOURCE_DIR}">"${BACKUP_DIR}/permissions.acl"
# 创建校验和
sha256sum"${TAR_FILE}">"${BACKUP_DIR}/checksum.sha256"
echo"Backup completed:${TAR_FILE}"
echo"ACL backup:${BACKUP_DIR}/permissions.acl"
恢复备份并校验权限:
#!/bin/bash
# script: restore_with_perms.sh
# 用途:从备份恢复文件及完整权限
BACKUP_FILE="/backup/20260403/backup.tar.gz"
ACL_FILE="/backup/20260403/permissions.acl"
TARGET_DIR="/data/app"
VERIFY_FILE="/tmp/restore_verify.txt"
echo"Starting restore with permissions..."
# 验证备份完整性
if[ -f"${BACKUP_FILE}.sha256"];then
echo"Verifying backup integrity..."
cd"$(dirname "${BACKUP_FILE}")"
if! sha256sum -c checksum.sha256;then
echo"ERROR: Backup checksum mismatch!"
exit1
fi
echo" Checksum verified"
fi
# 备份当前权限(以防万一)
getfacl -R"${TARGET_DIR}">"/tmp/pre_restore_acl.txt"2>/dev/null ||true
# 提取备份
tar -xzpf"${BACKUP_FILE}"-C"$(dirname "${TARGET_DIR}")"
# 恢复ACL
if[ -f"${ACL_FILE}"];then
echo"Restoring ACLs..."
setfacl --restore="${ACL_FILE}"
fi
# 验证恢复结果
getfacl -R"${TARGET_DIR}">"${VERIFY_FILE}"
echo"Restore completed. Verification saved to:${VERIFY_FILE}"
7. 常见权限问题排障
7.1 排障思路框架
权限问题排查遵循以下思路:
1. 确认问题现象 - 服务返回什么错误? - 是读取失败还是写入失败? - 哪些操作受影响? 2. 定位相关文件和目录 - 哪些文件被访问? - 文件的owner和group是什么? - 运行服务的用户是谁? 3. 检查权限链路 - 文件本身的权限是否正确? - 目录路径上所有父目录的权限? - ACL是否有额外限制? - 文件属性是否限制了操作? 4. 验证和修复 - 修复后测试 - 检查SELinux/AppArmor状态
7.2 典型故障:服务无法访问文件
故障现象:Nginx返回403 Forbidden,但文件存在。
排查脚本:
#!/bin/bash # script: troubleshoot_403.sh # 用途:排查Nginx 403错误 echo"=== Nginx 403 Troubleshooting ===" echo"" # 检查Nginx运行用户 echo"1. Nginx worker process user:" ps aux | grep"nginx: worker"| head -1 echo"" # 检查文件所有者 echo"2. Target file owner:" ls -la /var/www/html/index.html echo"" # 检查文件所在目录的权限链 echo"3. Permission chain:" TARGET="/var/www/html/index.html" while["$TARGET"!="/"];do ls -ld"$TARGET" TARGET=$(dirname"$TARGET") done echo"" # 检查SELinux上下文 echo"4. SELinux context:" ls -Z /var/www/html/index.html echo"" # 检查ACL echo"5. ACL settings:" getfacl /var/www/html/index.html 2>/dev/null ||echo"No ACL" echo"" # 检查nginx配置 echo"6. Nginx config user directive:" grep -r"^user"/etc/nginx/nginx.conf echo"" # 尝试用nginx用户读取 echo"7. Test read as nginx user:" su -s /bin/bash nginx -c"cat /var/www/html/index.html"2>&1 ||echo"Cannot read as nginx user"
常见原因及修复:
# 原因1:文件所有者不对 chown nginx:nginx /var/www/html/index.html # 原因2:目录权限不足 chmod 755 /var/www/html # 原因3:上级目录权限问题 chmod 755 /var/www # 原因4:SELinux问题 chcon -t httpd_sys_content_t /var/www/html/index.html restorecon -R /var/www/html # 原因5:ACL阻止访问 setfacl -b /var/www/html/index.html
7.3 典型故障:无法写入文件
故障现象:应用程序无法写入日志文件或数据文件。
排查脚本:
#!/bin/bash # script: troubleshoot_write.sh # 用途:排查写入权限问题 TARGET_PATH="$1" APP_USER="$2" if[ -z"$TARGET_PATH"] || [ -z"$APP_USER"];then echo"Usage:$0" exit1 fi echo"=== Write Permission Troubleshooting ===" echo"Target:${TARGET_PATH}" echo"App User:${APP_USER}" echo"" # 1. 检查路径上所有目录的写权限 echo"1. Write permission check (directory chain):" TARGET="$TARGET_PATH" while["$TARGET"!="/"];do PARENT=$(dirname"$TARGET") if[ -d"$TARGET"];then PERMS=$(stat-c"%a""$TARGET") OWNER=$(stat-c"%U:%G""$TARGET") echo" $TARGET:$PERMS($OWNER)" # 检查是否有写权限 if[ -w"$TARGET"];then echo" -> Current user CAN write" else echo" -> Current user CANNOT write" fi fi TARGET="$PARENT" done echo"" # 2. 检查目标文件的写权限 echo"2. File write permission:" if[ -f"$TARGET_PATH"];then ls -la"$TARGET_PATH" if[ -w"$TARGET_PATH"];then echo" -> File is writable" else echo" -> File is NOT writable" fi else echo" -> File does not exist, checking parent directory" if[ -w"$(dirname "$TARGET_PATH")"];then echo" -> Parent directory is writable (can create)" else echo" -> Parent directory is NOT writable" fi fi echo"" # 3. 检查ACL echo"3. ACL check:" getfacl"$TARGET_PATH"2>/dev/null | grep -E"^user:|^group:|^mask:" echo"" # 4. 检查文件系统属性 echo"4. File attributes (immutable flag):" lsattr"$TARGET_PATH"2>/dev/null ||echo"Cannot read attributes" echo"" # 5. 模拟app用户测试 echo"5. Test as${APP_USER}:" su -s /bin/bash"$APP_USER"-c"touch${TARGET_PATH}.test 2>&1"&& { rm -f"${TARGET_PATH}.test" echo" ->${APP_USER}CAN create files" } ||echo" ->${APP_USER}CANNOT create files"
7.4 典型故障:SUID程序异常
故障现象:设置了SUID位的程序无法正常运行。
#!/bin/bash # script: diagnose_suid_issue.sh # 用途:诊断SUID程序问题 PROGRAM="$1" if[ -z"$PROGRAM"];then echo"Usage:$0" exit1 fi echo"=== SUID Program Diagnostics ===" echo"Program:${PROGRAM}" echo"" # 1. 检查SUID位 echo"1. SUID bit status:" ls -la"$PROGRAM" PERMS=$(stat-c"%a""$PROGRAM") LAST3="${PERMS: -3}" FIRST="${PERMS1}" echo" Permission:$PERMS" echo" First digit (special):$FIRST" echo" Last 3 digits (basic):$LAST3" echo"" # 2. 检查文件所有者 echo"2. File owner:" stat-c"%U:%G""$PROGRAM" echo"" # 3. 检查是否shell脚本(危险) echo"3. File type:" file"$PROGRAM"| grep -q"script"&&echo" WARNING: This is a script, SUID shell scripts are dangerous!" file"$PROGRAM" echo"" # 4. 检查依赖库 echo"4. Shared libraries (if executable):" ldd"$PROGRAM"2>/dev/null | head -5 ||echo" Not a dynamic executable" echo"" # 5. 检查SELinux上下文 echo"5. SELinux context:" ls -Z"$PROGRAM" echo"" # 6. 检查文件系统是否noexec挂载 echo"6. Mount options for partition:" df -T"$PROGRAM"| tail -1 MOUNT_POINT=$(df -T"$PROGRAM"| tail -1 | awk'{print $2}') grep"$MOUNT_POINT"/proc/mounts ||echo" No specific mount options found"
7.5 权限问题综合检查脚本
#!/bin/bash
# script: full_permission_audit.sh
# 用途:全面审计系统权限状态
OUTPUT_DIR="/tmp/perm_audit_$(date +%Y%m%d)"
mkdir -p"${OUTPUT_DIR}"
echo"=== Full System Permission Audit ==="
echo"Output directory:${OUTPUT_DIR}"
echo""
# 1. 系统关键目录权限基线
{
echo"=== Critical Directory Permissions ==="
fordirin/etc /var /usr /home /root /tmp /boot;do
if[ -d"$dir"];then
ls -ld"$dir"
fi
done
} >"${OUTPUT_DIR}/01_critical_dirs.txt"
# 2. SUID/SGID文件清单
{
echo"=== SUID Files ==="
find / -typef -perm -4000 2>/dev/null | head -100
echo""
echo"=== SGID Files ==="
find / -typef -perm -2000 2>/dev/null | head -100
} >"${OUTPUT_DIR}/02_suid_sgid.txt"
# 3. World-writable文件和目录
{
echo"=== World-Writable Files (excluding /proc) ==="
find / -typef -perm -2 ! -path"/proc/*"! -path"/sys/*"2>/dev/null | head -50
echo""
echo"=== World-Writable Directories ==="
find / -typed -perm -2 ! -path"/proc/*"! -path"/sys/*"2>/dev/null | head -50
} >"${OUTPUT_DIR}/03_world_writable.txt"
# 4. 无主文件
{
echo"=== Unowned Files ==="
find / -nouser -o -nogroup 2>/dev/null | head -50
} >"${OUTPUT_DIR}/04_unowned.txt"
# 5. 异常权限检查
{
echo"=== Files with 777 Permission ==="
find / -typef -perm 777 2>/dev/null | head -50
echo""
echo"=== Root-owned files in /home ==="
find /home -typef -user root 2>/dev/null | head -20
} >"${OUTPUT_DIR}/05_anomalies.txt"
# 6. SSH目录权限
{
echo"=== SSH Directory and Key Permissions ==="
fordirin/root/.ssh /home/*/.ssh;do
if[ -d"$dir"];then
echo"Directory:$dir"
ls -la"$dir"
echo""
fi
done
} >"${OUTPUT_DIR}/06_ssh_perms.txt"
# 7. 重要配置文件权限
{
echo"=== Critical Config File Permissions ==="
forfilein/etc/passwd /etc/shadow /etc/group /etc/gshadow /etc/services;do
if[ -f"$file"];then
ls -la"$file"
fi
done
} >"${OUTPUT_DIR}/07_critical_configs.txt"
echo"Audit completed. Files in:${OUTPUT_DIR}"
ls -la"${OUTPUT_DIR}"
8. 安全最佳实践
8.1 权限配置原则
最小权限原则:只授予完成任务所需的最小权限,不要过度授权。
# 不好:给所有用户读权限 chmod 744 file.txt # 好:只给所有者读写权限 chmod 600 file.txt # 目录例外:需要浏览但不能写 chmod 755 /shared/readonly
目录权限优先:目录的写权限决定能否删除或创建文件,比文件本身权限更重要。
# 用户A创建了文件 touch /shared/file.txt # 所有者为A # 用户B如果在/shared目录有写权限,即使文件属于A,B也可以删除 # 解决:设置Sticky Bit chmod 1775 /shared
敏感文件特殊处理:关键配置文件设置不可修改属性。
# 系统配置文件防篡改 chattr +i /etc/passwd /etc/shadow /etc/group /etc/gshadow # 日志文件只追加 chattr +a /var/log/messages /var/log/secure # 验证 lsattr /etc/passwd # 应该显示 ----i------------- /etc/passwd
8.2 服务运行用户配置
原则:每个服务使用独立的低权限用户运行,避免服务被攻破后影响整个系统。
# 创建专用服务用户(禁止登录) useradd -r -s /sbin/nologin -d /var/lib/myapp myapp # 设置服务目录所有权 chown -R myapp:myapp /var/lib/myapp chown -R myapp:myapp /var/log/myapp # 确保目录权限正确 chmod 755 /var/lib/myapp chmod 750 /var/log/myapp
8.3 定期权限审计
#!/bin/bash # script: scheduled_permission_audit.sh # 用途:定期权限审计(建议加入cron) AUDIT_DIR="/var/audit/permissions" DATE=$(date +%Y%m%d) PREVIOUS_FILE="${AUDIT_DIR}/baseline.txt" CURRENT_FILE="${AUDIT_DIR}/current_${DATE}.txt" DIFF_FILE="${AUDIT_DIR}/diff_${DATE}.txt" mkdir -p"${AUDIT_DIR}" # 收集当前SUID文件快照 echo"Generating current SUID file list..." find / -typef -perm -4000 2>/dev/null | sort >"${CURRENT_FILE}" if[ -f"${PREVIOUS_FILE}"];then # 比对变更 diff"${PREVIOUS_FILE}""${CURRENT_FILE}">"${DIFF_FILE}" if[ -s"${DIFF_FILE}"];then echo"WARNING: SUID file changes detected!" cat"${DIFF_FILE}" # 这里可以加入邮件告警 fi # 备份旧基线 mv"${PREVIOUS_FILE}""${AUDIT_DIR}/baseline_$(date +%Y%m%d -d yesterday).txt" fi # 创建新基线 cp"${CURRENT_FILE}""${PREVIOUS_FILE}" echo"Audit completed"
8.4 文件权限基线核查
#!/bin/bash
# script: permission_compliance_check.sh
# 用途:检查权限是否符合安全基线
echo"=== Permission Compliance Check ==="
echo""
ISSUES=0
# 检查1:/etc/shadow应该是600
if[ -f /etc/shadow ];then
PERMS=$(stat-c"%a"/etc/shadow)
if["$PERMS"!="0"];then
echo"[FAIL] /etc/shadow permissions:$PERMS(expected 0)"
ISSUES=$((ISSUES+1))
else
echo"[PASS] /etc/shadow permissions:$PERMS"
fi
fi
# 检查2:/etc/passwd应该是644或更低
if[ -f /etc/passwd ];then
PERMS=$(stat-c"%a"/etc/passwd)
if["$PERMS"-gt"644"];then
echo"[FAIL] /etc/passwd permissions:$PERMS(expected <=644)"
ISSUES=$((ISSUES+1))
else
echo "[PASS] /etc/passwd permissions: $PERMS"
fi
fi
# 检查3:SSH私钥应该是600
if [ -f /root/.ssh/id_rsa ]; then
PERMS=$(stat -c "%a" /root/.ssh/id_rsa)
if [ "$PERMS" != "600" ]; then
echo "[FAIL] SSH private key permissions: $PERMS (expected 600)"
ISSUES=$((ISSUES+1))
else
echo "[PASS] SSH private key permissions: $PERMS"
fi
fi
# 检查4:.ssh目录应该是700
if [ -d /root/.ssh ]; then
PERMS=$(stat -c "%a" /root/.ssh)
if [ "$PERMS" != "700" ]; then
echo "[FAIL] .ssh directory permissions: $PERMS (expected 700)"
ISSUES=$((ISSUES+1))
else
echo "[PASS] .ssh directory permissions: $PERMS"
fi
fi
# 检查5:home目录应该是700
for user in /home/*; do
if [ -d "$user" ]; then
PERMS=$(stat -c "%a" "$user")
if [ "$PERMS" != "700" ]; then
echo "[FAIL] $user permissions: $PERMS (expected 700)"
ISSUES=$((ISSUES+1))
else
echo "[PASS] $user permissions: $PERMS"
fi
fi
done
# 检查6:/tmp应该是1777(带sticky bit)
PERMS=$(stat -c "%a" /tmp)
if [ "$PERMS" != "1777" ]; then
echo "[FAIL] /tmp permissions: $PERMS (expected 1777)"
ISSUES=$((ISSUES+1))
else
echo "[PASS] /tmp permissions: $PERMS"
fi
echo ""
if [ $ISSUES -eq 0 ]; then
echo "All checks passed!"
exit 0
else
echo "Found $ISSUES issue(s)"
exit 1
fi
9. 总结与检查清单
9.1 核心知识点回顾
基本权限模型:
UGO(User/Group/Others)三元组控制
rwx对应4/2/1,完整权限为777/755/644等
默认权限由umask控制,普通用户umask通常为0002
特殊权限:
SUID(4000):以文件所有者身份执行
SGID(2000):以文件所属组身份执行;目录继承组
Sticky Bit(1000):目录内文件只能所有者删除
ACL扩展:
getfacl查看、setfacl设置
支持用户和组的精细权限控制
目录可设置默认ACL实现继承
mask限制ACL条目的最大权限
文件属性:
chattr设置、lsattr查看
+i不可修改、+a只能追加
对root也生效(防御性属性)
排障思路:
确认运行用户身份
检查文件owner和permission
检查路径上所有父目录权限
检查ACL和文件属性
考虑SELinux/AppArmor
9.2 日常操作检查清单
部署新服务时:
[ ] 创建专用服务用户(useradd -r -s /sbin/nologin) [ ] 设置服务目录所有权(chown -R serviceuser:serviceuser) [ ] 目录权限755,文件权限644 [ ] 日志目录权限750或755 [ ] 需要写入的目录单独确认权限 [ ] 配置文件权限644,关键配置考虑chattr +i
备份和恢复时:
[ ] 使用tar -p保留权限和ACL [ ] 备份前后记录getfacl快照 [ ] 恢复后验证文件权限正确 [ ] 验证服务用户能正常读写所需文件
安全审计时:
[ ] 扫描SUID文件,确认都是必要的 [ ] 检查world-writable目录数量(越少越好) [ ] 验证/etc/shadow权限为0 [ ] 检查无主文件并清理或分配所有权 [ ] 确认/home目录权限为700 [ ] 验证SSH目录和密钥权限正确
9.3 常用命令速查表
| 操作 | 命令 |
|---|---|
| 查看文件权限 | ls -la file |
| 修改权限(数字) | chmod 755 file |
| 修改权限(符号) | chmod u+x file |
| 修改所有者 | chown user file |
| 修改所属组 | chgrp group file |
| 同时修改所有者和组 | chown user:group file |
| 设置SUID | chmod u+s file 或 chmod 4xxx file |
| 设置SGID | chmod g+s dir 或 chmod 2xxx dir |
| 设置Sticky Bit | chmod +t dir 或 chmod 1xxx dir |
| 查看ACL | getfacl file |
| 设置ACL | setfacl -m urw file |
| 删除ACL | setfacl -x u:user file |
| 查看文件属性 | lsattr file |
| 设置不可修改 | chattr +i file |
| 取消不可修改 | chattr -i file |
| 设置追加属性 | chattr +a file |
| 查找SUID文件 | find / -perm +4000 |
| 查找SGID文件 | find / -perm +2000 |
| 查找world-writable | find / -perm -2 |
9.4 排障流程图
权限问题发生 | v 确认问题现象(读失败?写失败?) | v 定位相关文件路径 | v 检查文件所有权(ls -la) | v 检查路径上所有父目录权限 | v 检查ACL(getfacl) | v 检查文件属性(lsattr) | v 如果是服务,检查服务运行用户(ps aux) | v 如果是服务,检查SELinux/AppArmor状态 | v 修复问题 | v 验证修复(测试操作是否成功)
参考信息
环境版本:
操作系统:Rocky Linux 9.4
内核版本:6.8.5
GNU Coreutils:9.1
bash版本:5.2.15
-
Linux
+关注
关注
88文章
11807浏览量
219508 -
文件
+关注
关注
1文章
597浏览量
26111 -
模型
+关注
关注
1文章
3810浏览量
52253 -
nginx
+关注
关注
0文章
193浏览量
13203
原文标题:十分钟搞懂 Linux 权限体系:新手必学的核心知识点
文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
一文搞懂UPS主要内容
Linux 中文件权限管理的探讨
Linux改变文件或目录的访问权限命令
浅谈Linux权限管理的ACL权限
linux文件访问权限怎么设置
Linux把目录权限给指定用户
Linux文件权限及Makefile
一文搞懂Linux权限体系
评论