Linux 权限
Linux 不仅支持多任务,还支持多用户同时使用。
拥有者,组成员,其他人
用户拥有文件和目录,拥有者具有对他所拥有的文件和目录的访问控制权,比如授权给其它用户、用户组、所有人(world)。
用户可以属于某个用户组。
账号创建时,会分配一个用户 id(uid
),和用户名匹配;会分配一个用户组 id(gid
),一个用户可以属于多个用户组。
id
# uid=1000(centos) gid=1000(centos) groups=1000(centos),4(adm),10(wheel),190(systemd-journal),994(docker) context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
用户账号定义在 /etc/passwd
;用户组定义在 /etc/group
。
里面包括超级用户和一些系统用户(system users)。
sudo cat /etc/passwd
## 用户名(登录名):uid :gid;账号真名(account’s real name):家目录(home directory):登录的 shell
# root❌0:0:root:/root:/usr/local/bin/zsh
# bin❌1:1:bin:/bin:/sbin/nologin
# daemon❌2:2:daemon:/sbin:/sbin/nologin
# adm❌3:4:adm:/var/adm:/sbin/nologin
# lp❌4:7:lp:/var/spool/lpd:/sbin/nologin
# sync❌5:0:sync:/sbin:/bin/sync
# shutdown❌6:0:shutdown:/sbin:/sbin/shutdown
# halt❌7:0:halt:/sbin:/sbin/halt
# mail❌8:12:mail:/var/spool/mail:/sbin/nologin
# operator❌11:0:operator:/root:/sbin/nologin
# games❌12💯games:/usr/games:/sbin/nologin
# ftp❌14:50:FTP User:/var/ftp:/sbin/nologin
# nobody❌99:99:Nobody:/:/sbin/nologin
# systemd-network❌192:192:systemd Network Management:/:/sbin/nologin
# dbus❌81:81:System message bus:/:/sbin/nologin
# polkitd❌999:998:User for polkitd:/:/sbin/nologin
# rpc❌32:32:Rpcbind Daemon:/var/lib/rpcbind:/sbin/nologin
# rpcuser❌29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
# nfsnobody❌65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
# sshd❌74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
# postfix❌89:89::/var/spool/postfix:/sbin/nologin
# chrony❌998:995::/var/lib/chrony:/sbin/nologin
# centos❌1000:1000:Cloud User:/home/centos:/usr/local/bin/zsh
# tss❌59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
sudo cat /etc/group
# root❌0:
# bin❌1:
# daemon❌2:
# sys❌3:
# adm❌4:centos
# tty❌5:
# disk❌6:
# lp❌7:
# mem❌8:
# kmem❌9:
# wheel❌10:centos
# cdrom❌11:
# mail❌12:postfix
# man❌15:
# dialout❌18:
# floppy❌19:
# games❌20:
# tape❌33:
# video❌39:
# ftp❌50:
# lock❌54:
# audio❌63:
# nobody❌99:
# users❌100:
# utmp❌22:
# utempter❌35:
# input❌999:
# systemd-journal❌190:centos
# systemd-network❌192:
# dbus❌81:
# polkitd❌998:
# rpc❌32:
# ssh_keys❌997:
# cgred❌996:
# rpcuser❌29:
# nfsnobody❌65534:
# sshd❌74:
# postdrop❌90:
# postfix❌89:
# chrony❌995:
# centos❌1000:
# docker❌994:centos
# stapusr❌156:
# stapsys❌157:
# stapdev❌158:
# tss❌59:
# 账号密码
sudo file /etc/shadow
# /etc/shadow: ASCII text
sudo cat /etc/shadow
# root:$6$wFw0kDkp$rBpc7bQCWtTxz65jJm2C/79EGKfYs0JFMbGhnDLb2NigPd5isoU.Bbq33nvWwU.JdZgOtv47JBZJuzh1P3dTH/:18178:0:99999:7:::
# bin:*:17632:0:99999:7:::
# daemon:*:17632:0:99999:7:::
# adm:*:17632:0:99999:7:::
# lp:*:17632:0:99999:7:::
# sync:*:17632:0:99999:7:::
# shutdown:*:17632:0:99999:7:::
# halt:*:17632:0:99999:7:::
# mail:*:17632:0:99999:7:::
# operator:*:17632:0:99999:7:::
# games:*:17632:0:99999:7:::
# ftp:*:17632:0:99999:7:::
# nobody:*:17632:0:99999:7:::
# systemd-network:!!:17687::::::
# dbus:!!:17687::::::
# polkitd:!!:17687::::::
# rpc:!!:17687:0:99999:7:::
# rpcuser:!!:17687::::::
# nfsnobody:!!:17687::::::
# sshd:!!:17687::::::
# postfix:!!:17687::::::
# chrony:!!:17687::::::
# centos:$6$RsIlxZTh$sDEX4PGPJOjf.weyY9wmYGT/x3T63ZnWiBogI3DAe/RJ2ndwAAXLxfyE5KdID7TTJbmOXcY0I07LE.vgr3ldG1:18178:0:99999:7:::
# tss:!!:18399::::::
账号创建时,/etc/passwd
、/etc/group
、/etc/shadow
文件都会更新。
While many Unix-like systems assign regular users to a common group such as
users
, modern Linux practice is to create a unique, single-member group with the same name as the user. This makes certain types of permission assignment easier
读,写,执行
文件和目录的访问权限分为读、写、执行。
ls -l
的前 10 个字符称为文件属性。第一个字符是文件类型;后九个是 file mode,分别表示文件拥有者、文件的组拥有者(file’s group owner)和所有其他人对该文件的读、写、执行权限。
> foo.txt
ls -l foo.txt
# -rw-r--r-- 1 root root 0 Jul 13 03:47 foo.txt
常见的文件类型:
Attribute | File type |
---|---|
- |
普通文件 |
d |
目录 |
l |
软链接(symbolic link)。软链接的剩余文件属性永远是 rwxrwxrwx ,称为 dummy values。真实的文件属性要看软链接指向的文件。 |
c |
A character special file. This file type refers to a device that handles data as a stream of bytes, such as a terminal or /dev/null . |
b |
A block special file. This file type refers to a device that handles data in blocks, such as a hard drive or DVD drive. |
常见的权限属性:
Attribute | Files | Directories |
---|---|---|
r |
允许打开并读取文件 | 若同时设置了执行属性,则允许罗列出目录包含的内容 |
w |
允许文件被写入或截取(truncated);带有此属性不表示可以重命名或删除文件,这些由目录属性控制 | 若同时设置了执行属性,则允许创建、删除、重命名目录里的文件 |
x |
允许将文件作为一个程序来执行;若是用脚本语言编写的程序,则必须同时具备读属性才可以被执行 | 允许进入目录(Allows a directory to be entered, e.g., cd directory) |
chmod
: change file mode (permissions)
只有 superuser 和拥有者可以修改文件或目录的权限。
chmod
支持以八进制和符号两种中怒斥方式指定权限。
八进制:
Octal | Binary | File mode |
---|---|---|
0 | 000 | — |
1 (2^0) | 001 | –x |
2 (2^1) | 010 | -w- |
3 | 011 | -wx |
4 (2^2) | 100 | r– |
5 | 101 | r-x |
6 | 110 | rw- |
7 | 111 | rwx |
> foo.txt
# 3 位数的八进制数从左到右分别表示 owner,group owner,others
chomod 640 foo.txt
ls -l foo.txt
# -rw-r-----. 1 centos centos 3 Jun 22 15:11 foo.txt
符号的标识方式分为 3 个部分:
-
变更会影响的对象;
Symbol Meaning u
user 的简写,表示文件或目录的所有者 g
组的所有者 o
others 的简写,表示所有其他人 a
all 的简写,是 u
、g
和o
的总和(若未指定字符,默认是a
) -
执行的变更操作;
+
、-
分别表示增、减某项权限;=
用于指定特定权限,其它权限会被移除。
-
设置的权限。
- 用
r
、w
和x
表示。
- 用
--recursive
用于同时修改文件和目录,不常用,因为鲜有文件和目录权限相同的场景。
示例:
Notation | Meaning |
---|---|
u+x |
为所有者增加执行权限 |
u-x |
给所有者减去执行权限 |
+x |
等价于 a+x |
o-rw |
为其他人减去读写权限 |
go=rw |
给组的所有者和其他人设置读写权限,若他们有执行权限,则执行权限会被移除 |
u+x,go=rx |
多个规则的指定用逗号分隔 |
umask
umask
用于设置新建文件时默认赋予的权限,使用八进制来表示比特掩码,表示要移除的权限(uses octal notation to express a mask of bits to be removed from a file’s mode attributes)。
rm -f foo.txt
# 查看当前值
umask
# 0022
> foo.txt
ls -l foo.txt
# -rw-r--r-- 1 root root 0 Jul 13 13:42 foo.txt
rm foo.txt
umask 0000
> foo.txt
ls -l foo.txt
# -rw-rw-rw- 1 root root 0 Jul 13 13:43 foo.txt
# 恢复
umask 0022
umask 值取反后按位与(效果是 umask 值的二进制表示的某个位置是 1,相应的权限就被移除):
# umask 值是 0000,取反后 111 111 111 111,即不掩蔽
# 此时新建文件的默认权限是 -rw-rw-rw-,即不掩蔽的默认权限是 110 110 110
# umask 设置成 0022(000 000 010 010)后,取反后得到 111 111 101 101,
# 与 110 110 110 执行按位与,得到 111 110 100 100,即 -rw-r--r--
特殊权限
常见的权限掩码用 3 位数的八进制表示,但用 4 位数表示其实更准确。除了读、写、执行外还存在一些不常用的权限设置。
setuid
bit(八进制表示是 4000):
- 当设置在可执行文件上时,它会把 effective user ID 从真实用户(real user,运行可执行文件的用户)改成可执行文件的拥有者。普通用户运行
setuid root
的程序时,该程序具有 superuser 的权限(如访问仅有 superuser 才能访问的文件、目录)。 - 这样的用法可能存在安全风险,需要谨慎使用。
-
setgid
bit(八进制表示是 2000):
- 当设置在目录上时,目录中新建的文件的所属用户组会从文件创建者所属的用户组变为目录所属的用户组。
- 适用于共享一个目录所有文件的场景。
sticky
bit(八进制是 1000):
- Unix 遗留物(Unix 支持将可执行文件标记为 not swappable),设置在文件上时被忽略,设置在目录上时,则会阻止目录拥有者、文件拥有者和 superuser 以外的用户去删除或重命名目录里的文件。
- 通常用于做共享目录的访问控制,如
/tmp
。
示例:
# assigning setuid to a program
chmod u+s program
# a program that is setuid
# -rwsr-xr-x
# assigning setgid to a directory
chmod g+s dir
# a directory that has the setgid attribute
# drwxrwsr-x
# assigning the sticky bit to a directory
chmod +t dir
# a directory with the sticky bit set
# drwxrwxrwt
切换身份
切换身份的 3 种方式:
- 登出后以另一个用户身份登录
su
(shift user)- 采用另一个用户的身份发起一个新的 shell 会话或是以另一个用户的身份执行一条命令。
sudo
(superuser do)- 管理员设置配置
sudo
去定义一些允许普通用户以其它身份(通常是 root)去执行的命令。 /etc/sudoers
- 管理员设置配置
su
语法:
su [-[l]] [user]
su -c 'command' # 执行单条命令
# start a shell for the superuser ($ becomes #)
su - # prompted for the superuser’s password
# return to previous shell
exit
# It is important to enclose the command in quotes
# as we do not want expansion to occur in our shell but rather in the new shell
su -c 'ls -l /root/*'
指定 -l
后,得到的 shell 是指定用户的 login shell(需要输入指定用户的密码),该用户的环境配置会加载进来,工作目录也会切换到该用户的家目录。
-l
可以缩写成 -
。
若未指定用户,默认是 superuser。
使用 sudo
执行命令不需要其它用户的密码,需要当前用户的密码。
sudo
不会新建新的 shell,也不会加载另一个用户的环境配置。所以 sudo
后跟的命令不需要用括号括起来(展开在当前 shell 展开,不需要传到新 shell 去展开)。
sudo -i
可以启动一个 superuser session(和 su -
类似)。
大多数配置中 sudo
会信任一个用户一定时长,直到过期。
# 切换到 root(不需要输入 root 密码)
sudo su
# list user's privileges or check a specific command; use twice for longer format
sudo -l
Windows 中,普通用户要执行 superuser 才能执行的任务,需要赋予普通用户管理员权限(以用户为维度划分)。但这样做后,普通用户执行的程序也具有相同的管理员权限,这一点可以被恶意软件利用。
Unix 的处理方式是只在需要 superuser 权限的时候采取赋予。
使用 su
不需要有类似 sudo
的配置文件,用户倾向于以 root 身份执行一切命令以避免权限问题,这样权限管理就等同于和 Windows 一样,不建议。
Ubuntu 通过不允许给 root 账号设置密码,使得用户不能以 root 身份登录,只通过 sudo
来授予 superuser 的权限。初始用户的账户通过 sudo
被赋予了 superuser 的完整权限,由他为后续用户分配权限。
chown
chown
用于变更文件或目录的拥有者和组的所有者。
chown [owner][:[group]] file...
执行 chown
需要 superuser 权限。
示例:
参数 | 结果 |
---|---|
bob |
将文件的拥有权从文件的当前拥有者变更为 bob |
bob:users |
将文件的拥有权从文件的当前拥有者变更为 bob,将文件的组的所有者变为 users |
:admins |
将文件的组的所有者变为 admins,文件拥有者不变 |
bob: |
将文件的拥有权从文件的当前拥有者变更为 bob,将文件的组的所有者变为 bob 的 Primary group (the login group of user bob) |
janet 有 superuser 权限,tony 没有。janet 想从自己的家目录拷贝一个文件到 tony 的家目录,同时希望 tony 有权限编辑该文件,所以 janet 将拷贝的文件的所有权由 janet 改成 tony:
# tilde expansion
sudo cp myfile.txt ~tony
sudo ls -l ~tony/myfile.txt
# -rw-r--r-- 1 root root root 2018-03-20 14:30 /home/tony/myfile.txt
sudo chown tony: ~tony/myfile.txt
# tony 的 login group 也是 tony
sudo ls -l ~tony/myfile.txt
# -rw-r--r-- 1 tony tony tony 2018-03-20 14:30 /home/tony/myfile.txt
老版本的 Unix 中 chown
只能改变文件所有权,不能改变组的拥有者。改变组的拥有者要用单独的 chgrp
命令。
Linux 中有两种组:
- Primary group
- 一个用户登录后被赋予的组,通常组名和用户名相同。该用户创建的进程、文件的组的所有者都是 Primary group。
- Secondary or supplementary group
- 用户可以成为其它组的成员,在需要文件共享等场景很有用。
设置一个共享目录
bill 和 karen 需要建立一个共享目录共享彼此的音乐文件,用户 bill 可以通过 sudo
使用 superuser 权限。
# 创建一个名为 music 的组
sudo groupadd music
# 创建用户;添加用户到 Secondary group;查看 用户所属的组
adduser bill
usermod -aG sudo bill
usermod -aG music bill
groups bill
adduser karen
usermod -aG music karen
groups karen
su - bill
umask
# 0002
umask 0022
# bill 在操作家目录以外的文件,需要 superuser 权限
sudo mkdir /usr/local/share/Music
ls -ld /usr/local/share/Music
# drwxr-xr-x 2 root root 4096 Jul 15 01:13 /usr/local/share/Music
# 755
# Music group owner 由 root 变为 music
sudo chown :music /usr/local/share/Music
ls -ld /usr/local/share/Music
# drwxr-xr-x 2 root music 4096 Jul 15 01:13 /usr/local/share/Music
# 为 music group 对 Music 目录增加 w 权限
sudo chmod 775 /usr/local/share/Music
ls -ld /usr/local/share/Music
# drwxrwxr-x 2 root music 4096 Jul 15 01:13 /usr/local/share/Music
> /usr/local/share/Music/test_file
# Music 下新建的 test_file 属于 bill 组(primary group)
ls -l /usr/local/share/Music
# -rw-r--r-- 1 bill bill 0 Jul 15 01:17 test_file
sudo chmod g+s /usr/local/share/Music
ls -ld /usr/local/share/Music
# drwxrwsr-x 2 root music 4096 Jul 15 01:17 /usr/local/share/Music
rm /usr/local/share/Music/test_file
# Music 下新建的 test_file 属于 music (目录的组的所有者)
> /usr/local/share/Music/test_file
ls -l /usr/local/share/Music/test_file
# -rw-r--r-- 1 bill music 0 Jul 15 01:20 /usr/local/share/Music/test_file
# bill 在 Music 下创建的目录 bill_music,music 组其它成员无写入权限(umask 对新建的目录也起作用)
sudo mkdir /usr/local/share/Music/bill_music
ls -ld /usr/local/share/Music/bill_music
# drwxr-sr-x 2 root music 4096 Jul 15 01:27 /usr/local/share/Music/bill_music
rm /usr/local/share/Music/test_file
rm -rf /usr/local/share/Music/bill_music
# 允许 music 组的其它用户在 bill_dir 下创建文件、目录
umask 0002
> /usr/local/share/Music/test_file
mkdir /usr/local/share/Music/bill_dir
ls -l /usr/local/share/Music
# [ ] 新建文件和新建目录的权限不一样
# drwxrwsr-x 2 bill music 4096 Jul 15 01:35 bill_dir
# -rw-rw-r-- 1 bill music 0 Jul 15 01:34 test_file
# 加 sudo 后 owner 是 root(不加是 bill)
sudo mkdir /usr/local/share/Music/bill_dir2
sudo touch /usr/local/share/Music/test_file2
ls -l /usr/local/share/Music
# drwxr-sr-x 2 root music 4096 Jul 15 01:37 bill_dir2
# -rw-r--r-- 1 root music 0 Jul 15 01:39 test_file2
# umask 的设置只在当前 session 有效,
修改密码
passwd [user]
passwd
可以修改自己的密码;管理员可以修改其他用户的密码。
passwd
对密码强度有要求,太短、太像前一个密码、字典的单词或是太易猜的都不能通过。
管理员可以通过 passwd
进行锁定账户、设置密码过期时间等操作。