账号和用户组
系统管理员的主要工作就是管理账号。我们先来了解一下linux系统是如何识别每个用户的。
用户标识符:UID和GID
linux的用户至少有2个ID,也就是UID用户ID和GID用户组ID。虽然登录的时候输入的是用户名,但其实系统识别的是这个两个ID。
使用id命令,可以查看用户的这两个id
[root@node4 ~]# id root
uid=0(root) gid=0(root) 组=0(root)
[root@node4 ~]# id nginx
uid=1000(nginx) gid=1001(nginx) 组=1001(nginx)
通过这两个ID,Linux系统就把用户和群组和文件联系了起来,总而实现了权限管理。
用户账号
当我们登录Linux系统时,系统大概做了如下事情:
- 首先查找/etc/passwd里是否有输入的账号,如果有的话获取UID和GID
- 从/etc/shadow文件中核对密码
- 如果以上ok,进入shell界面
接下来分别介绍passwd和shadow这两个文件
-
/etc/passwd
每一行代表一个账号。其中比较靠前的是系统自带的账号。
[root@node4 ~]# head -n 4 /etc/passwd root:x:0:0:root:/root:/bin/bash bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin
每一行的结构如下:
- 账号名称:例如root
- 密码:现在是x,早期的UNIX系统,密码就存在这里。现在已废弃。
- UID和GID:比如第一行就是0:0。系统账号的范围是1-999,用户账号范围是1000-60000
- 用户信息说明字段
- 用户家目录
- shell:用户登录后提供的默认shell
-
/etc/shadow
[root@node4 ~]# head -n 4 /etc/shadow root:$6$Rj7coYh/STyMcxjn$ZY.l1SDPcsJv1NUwiA.INYB7Q/bTxAXHFyRTm42M/qxdPWAt9Ly3eQSpu1Xn5v9LkxLJITwb6igAUPMOD.mBj/::0:99999:7::: bin:*:18353:0:99999:7::: daemon:*:18353:0:99999:7::: adm:*:18353:0:99999:7:::
shadow文件的每一行的结构如下:
- 账号名称
- 密码:此处存储的是真正的密码
- 最近修改密码的日期:为空的话,说明密码没修改过
- 密码不可被修改的天数:如果是0,表示密码随时可以修改
- 密码需要修改的天数:就是密码有效期,99999基本就是无需修改
- 密码需要修改前的警告天数:默认是7
- 密码过期后的密码失效天数
- 账号失效日期
- 保留字段
用户组
组相关的信息存放在/etc/group和/etc/gshadow中,我们继续来了解一下
-
/etc/group
[root@node4 ~]# head -n 4 /etc/group root:x:0: bin:x:1: daemon:x:2: sys:x:3:
每一行代表一个用户组,结构是组名、组密码、GID、用户组中的账号名称
-
有效用户组(effective group和初始用户组(initial group
passwd里存储的GID就是用户的初始用户组,也就是说,用户登录系统默认拥有这个用户组的权限。
如果一个用户属于多个群组,他将拥有这些群组的所有权限。
但如果用户新建一个文件,该文件的默认用户组,取决于用户的有效用户组。
用groups命令可以查看用户有效群组
[root@node4 ~]# usermod -a -G users nginx [root@node4 ~]# groups nginx nginx : nginx users
我们通过如下命令,新建一个用户,指定群组并允许登录
[root@node4 ~]# groupadd testgroup [root@node4 ~]# useradd -g testgroup testuser -s /bin/bash [root@node4 ~]# usermod -a -G users testuser [root@node4 ~]# passwd testuser
用testuser登录后,新键一个文件,可以发现文件权限是属于有效群组的
[testuser@node4 ~]$ groups testgroup users [testuser@node4 ~]$ touch testfile [testuser@node4 ~]$ ll testfile -rw-r--r-- 1 testuser testgroup 0 4月 22 21:42 testfile
-
newgrp:有效用户组的切换
可以使用newgrp命令切换有效群组为已经拥有的群组,例如
[testuser@node4 ~]$ newgrp users [testuser@node4 ~]$ groups users testgroup
这时候你会发现向上的命令无法使用历史命令了,这是因为newgrp事实上是通过新开了一个shell的方式来实现切换有效用户组的,可以通过exit退出。退出后就又变成之前的用户组了。
[testuser@node4 ~]$ exit exit [testuser@node4 ~]$ groups testgroup users
-
/etc/gshadow
[root@node4 ~]# head -n 4 /etc/gshadow root::: bin::: daemon::: sys:::
组名:密码:用户组管理员账号:用户组中用户账号(和etc/group相同
gshadow最大的功能就是建立用户组管理员。该管理员有权将用户加入到自己的组中。
账号管理
新增用户useradd
使用useradd命令来添加一个用户
useradd [-u UID] [-g 初始用户组] [-G 次要用户组] [-mM] \
> [-c 说明栏] [-d 家目录] [-s shell] 账号名称
参数说明:
-u 指定UID -g 初始用户组
-M 不创建家目录,系统账号默认此参数
-m 创建家目录,普通账号默认此参数
-c 对应passwd第五列,账号说明
-d 指定家目录,必须使用绝对路径
-r 建立一个系统账号
-s shell 默认指定/bin/shell
例如:
[root@node4 ~]# useradd -g testgroup testuser -s /bin/bash
userad命令建立用户的默认值,可以使用-D查看
[root@node4 ~]# useradd -D
GROUP=100
HOME=/home
INACTIVE=-1
EXPIRE=
SHELL=/bin/bash
SKEL=/etc/skel
CREATE_MAIL_SPOOL=yes
删除用户userdel
使用如下命令就可以删除用户
userdel username
-r 删除的同时删除家目录
默认情况下,如果用户所属的组没有其他用户了,就会一并删除用户组。
这取决于/etc/login.defs的USERGROUPS_ENAB 参数
设置密码passwd
默认创建的用户是无法登录的,需要用passwd设置密码
passwd 账号名称
参数:
-l 锁定用户
-u 解锁用户
--stdin 管道数据作为密码输入
-S 显示密码大部分信息
注意,如果passwd后什么都不加,表示修改当前用户密码。
使用stdin的一个例子:
# stdin不是所有Linux版本都支持,请使用man passwd确认
echo "abc@1234" | passwd --stdin usera
好处是不用多次输入密码确认了,缺点是该命令会保留在历史命令中,密码很容易泄露。所以stdin一般用在脚本批量创建多个用户时。
锁定登录和解锁,事实上是通过在/etc/shadow里给密码加上!!来实现的
[root@node4 ~]# passwd -l testuser
锁定用户 testuser 的密码 。
passwd: 操作成功
[root@node4 ~]# passwd -S testuser
testuser LK 2024-04-22 0 99999 7 -1 (密码已被锁定。)
[root@node4 ~]# grep testuser /etc/shadow
testuser:!!$6$oJh4Uczu$dwkoctc/RXPZI2nL3YyxSMJCzel1VPTjarVkP/P53tFhKS7coIbJXAC9rhdxKyytmmvPkEGvjqmSHY9p/4kVF0:19835:0:99999:7:::
[root@node4 ~]# passwd -u testuser
解锁用户 testuser 的密码。
passwd: 操作成功
[root@node4 ~]# grep testuser /etc/shadow
testuser:$6$oJh4Uczu$dwkoctc/RXPZI2nL3YyxSMJCzel1VPTjarVkP/P53tFhKS7coIbJXAC9rhdxKyytmmvPkEGvjqmSHY9p/4kVF0:19835:0:99999:7:::
如果希望用户第一次登录时修改密码,需要通过change命令
user add agetest
echo "123456" | passwd --stdin agetest
change -d 0 agetest
查看用户密码过期情况
chage -l username
用户修改usermod
usermod -参数 username
-c 账户说明
-d 修改家目录
-e 过期日期
-f 密码过期时间,0立即失效 -1 永不失效
-g 初始用户组
-G 次要用户组
-l 修改用户名称
-s shell文件
-u UID
-L 锁定
-U 解锁
用户功能
上面的添加删除用户,都是root用户才有的功能,那么普通用户有哪些功能呢
-
id 查看用户信息,也可以确定某用户是否存在
[testuser@node4 ~]$ id uid=1002(testuser) gid=1003(testgroup) 组=1003(testgroup),100(users)
-
finger 也可以列出用户信息,但可能包含机密信息,所以该命令默认已经不安装。可以使用yum安装
[root@node4 ~]# finger Login Name Tty Idle Login Time Office Office Phone Host root root pts/0 Apr 25 19:54 (192.168.32.1) testuser hanayo pts/1 Apr 25 20:49 shanghai 456123 (192.168.32.1)
-
chfn 修改用户信息
[testuser@node4 ~]$ chfn Changing finger information for testuser. 名称 []: hanayo katyotin^H^H chfn: control characters are not allowed 名称 []: hanayo 办公 []: shanghai 办公电话 []: 456123 住宅电话 []: 182222密码: Finger information changed.
-
chsh 也就是change shell
[root@node4 ~]# chsh -l /bin/sh /bin/bash /usr/bin/sh /usr/bin/bash
用户组修改
用户组的修改其实和用户比较类似
-
groupadd 添加用户组
groupadd -g gid groupname -g 指定GID -r 建立系统用户组
-
groupmod 修改用户组
groupmod -g gid -n group_name groupname -g 修改GID -n 修改组名
-
groupdel 删除用户组。如果当前组有用户,删除会报错
groupdel groupname
-
gpasswd:用户组管理员
gpasswd groupname gpasswd -A user1 -M user3 groupname group -rR groupname -A 将改组管理权授权给user1 -M 将用户加入该组 -r 删除groupname的密码 -R 让groupname的密码失效 gpasswd -ad user groupname -a 用户加入组 -d 用户从组删除
ACL权限设置
仅仅依靠owner,group,others搭配r,w,x来进行权限管理是不够的。Linux还有一种详细的权限管理,也就是ACL Access Control List
用以下命令可以确认当前系统是否支持acl:
[root@node4 ~]# dmesg | grep -i acl
[ 1.215136] systemd[1]: systemd 219 running in system mode. (+PAM +AUDIT +SELINUX +IMA -APPARMOR +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 -SECCOMP +BLKID +ELFUTILS +KMOD +IDN)
[ 3.483737] SGI XFS with ACLs, security attributes, no debug enabled
ACL权限设置getfacl和setfacl
-
setfacl 设置详细权限
setfacl -bkRd [{-m|-x} acl参数] 目标文件名 -m 设置后续的acl参数 -x 删除后续acl参数 -b 删除所有acl参数 -k 删除默认acl参数 -R 递归设置 -d 设置默认acl参数,对目录设置时使用
以下是一个实例
[root@node4 ~]# touch acl_test1 [root@node4 ~]# ll acl_test1 -rw-r--r-- 1 root root 0 4月 25 21:41 acl_test1 [root@node4 ~]# setfacl -m u:testuser:rx acl_test1 [root@node4 ~]# ll acl_test1 -rw-r-xr--+ 1 root root 0 4月 25 21:41 acl_test1 用acl修改权限后,权限多了个+
-
getfacl 查看权限
getfacl filename
查看刚刚的权限
[root@node4 ~]# getfacl acl_test1 # file: acl_test1 # owner: root # group: root user::rw- # 所有者的权限 user:testuser:r-x # 特定用户的权限 group::r-- # 所属用户组默认权限 mask::r-x # 有效权限 other::r-- # 其他人的权限
-
设定单一用户组权限:g:用户组:权限
[root@node4 ~]# setfacl -m g:testgroup:rx acl_test1 [root@node4 ~]# getfacl acl_test1 # file: acl_test1 # owner: root # group: root user::rw- user:testuser:r-x group::r-- group:testgroup:r-x # 该群组权限已设置 mask::r-x other::r--
-
mask是啥?mask的意义是**用户或群组的权限,只有在mask的群星范围内,才会生效。**如下,因为权限交集只有r,所以testuser的权限只有r。mask通常用来设定权限的最大范围。
[root@node4 ~]# setfacl -m m:r acl_test1 [root@node4 ~]# getfacl acl_test1 # file: acl_test1 # owner: root # group: root user::rw- user:testuser:r-x #effective:r-- group::r-- group:testgroup:r-x #effective:r-- mask::r-- other::r--
-
文件夹权限继承
用acl设定的权限,默认目录中的信件文件夹是不继承的,需要加上 d
setfacl -m d:u:testuser:rx /mydir/mydir
-
取消所有权限设置,注意-x是删除某个用户的acl设置,而-b是删除所有
setfacl -x u:testuser /mydir/mydir setfacl -x d:u:testuser /mydir/mydir# 设置某用户不可使用某目录,注意权限用-代指 setfacl -m u:usera:- /dir/dir
用户身份切换
在生产环境中,一般使用普通用户登录用户,这样比较安全。这样有以下好处
- 避免危险操作:比如著名的【rm -rf /】如果你用root用户执行了这个,就要准备提桶跑路了。而用一般用户就没权限执行这个,就不用担心了
- 用较低权限启动服务:比如nginx服务用nginx用户启动,这样就算这个用户被攻击了,系统不至于被完全攻陷
- 软件本身限制:某些远程ssh工具不允许root直接登录
SU命令
su是最常用的身份切换命令
su -lm -c 命令 username
- 如果只有- 比如【su -】代表切换root,跟用户名表示切换其他用户
-c 仅执行一次命令
-l 后面需要加上想要切换的用户的账号
-m 使用目前的环境设置, 而不是新用户的
从root切换成testuser
[root@node4 ~]# su testuser
[testuser@node4 root]$ env | grep 'root'
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/usr/java/default/bin:/usr/java/default/bin:/opt/zookeeper-3.4.6/bin:/opt/hadoop-2.6.5/bin:/opt/hadoop-2.6.5/sbin:/opt/nginx/sbin:/root/bin
MAIL=/var/spool/mail/root
PWD=/root
# 可以看到已经切换了,但是环境变量中很多还是root的值
[testuser@node4 root]$ exit
exit # 通过exit命令可以退出su环境
通过上面例子可以看出,只使用su命令切换身份的话,很多变量不会被修改。所以切换用户,建议加上-,如下
[root@node4 ~]# su - testuser
上一次登录:六 4月 27 09:52:45 CST 2024pts/0 上
[testuser@node4 ~]$ env | grep 'root'
[testuser@node4 ~]$ env | grep 'testuser'
USER=testuser
MAIL=/var/spool/mail/testuser
PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/usr/java/default/bin:/usr/java/default/bin:/opt/zookeeper-3.4.6/bin:/opt/hadoop-2.6.5/bin:/opt/hadoop-2.6.5/sbin:/opt/nginx/sbin:/home/testuser/.local/bin:/home/testuser/bin
PWD=/home/testuser
HOME=/home/testuser
LOGNAME=testuser
# 可以看到变量都已经变成新的了
[testuser@node4 ~]$ exit
登出 # 同样使用exit退出
假如我们当前是用普通用户登录的,只是想用root执行一个命令,
# testuser用户无权限
[testuser@node4 ~]$ head -n 3 /etc/shadow
head: 无法打开"/etc/shadow" 读取数据: 权限不够
[testuser@node4 ~]$ su - -c "head -n 3 /etc/shadow"
密码: <==此处输入密码
root:$6$Rj7coYh/STyMcxjn$ZY.l1SDPcsJv1NUwiA.INYB7Q/bTxAXHFyRTm42M/qxdPWAt9Ly3eQSpu1Xn5v9LkxLJITwb6igAUPMOD.mBj/::0:99999:7:::
bin:*:18353:0:99999:7:::
daemon:*:18353:0:99999:7:::
[testuser@node4 ~]$ 身份还是testuser,已经成功执行了命令
总结一下:
- 使用【su - username】切换用户,才会完整切换到新用户环境
- 如果仅执行一次命令,可以使用【su - -c “命令”】
- 使用root切换到其他用户,不需要输入密码
SUDO命令
上述命令切换有一个问题,就是切换到root权限需要知道root的密码。这显然是不安全的,而SUDO命令可以让普通用户以root身份执行命令。
-
sudo的用法(默认情况下sudo只有root可以使用
sudo [-b] [-u username] 参数: -b: 后台执行命令 -u: 以该用户身份执行命令
例1:
# 使用sshd的身份建立一个新文件,注意看,权限是sshd [root@node4 ~]# sudo -u sshd touch /tmp/mysshd [root@node4 ~]# ll /tmp/mysshd -rw-r--r-- 1 sshd sshd 0 4月 27 10:09 /tmp/mysshd
例2:
# 用testuser的身份建立文件 [root@node4 tmp]# sudo -u testuser sh -c "mkdir ~testuser/www; \ >cd ~testuser/www; echo 'hello'>index.html"
-
visudo和/etc/sudoers
用户是否能够使用sudo命令,取决于/etc/sudoers的设置值。/etc/sudoers拥有特殊的语法,必须使用visudo命令去修改。我们通过以下几个例子来说明
例1:单一用户可以使用root所有命令
[root@node4 ~]# visudo ...... ## Allow root to run any commands anywhere root ALL=(ALL) ALL <== 找到这一行 testuser ALL=(ALL) ALL <== 新增这一行,注意所有ALL都是大写 ......
visudo实际上就是用vi命令修改这个文件,上面新增的含义是
用户账号 登录者来源主机=(可切换的身份) 可执行的命令
用testuser试试
# 没有权限执行的命令,用sudo就可以执行了 [testuser@node4 ~]$ tail -n 1 /etc/shadow tail: 无法打开"/etc/shadow" 读取数据: 权限不够 [testuser@node4 ~]$ sudo tail -n 1 /etc/shadow testuser:$6$oJh4Uczu$dwkoctc/RXPZI2nL3YyxSMJCzel1VPTjarVkP/P53tFhKS7coIbJXAC9rhdxKyytmmvPkEGvjqmSHY9p/4kVF0:19835:0:99999:7:::
例2:使用wheel用户组
在centos7以后,wheel默认是启用的
[root@node4 ~]# visudo ... testuser ALL=(ALL) ALL # 把这一行删掉 ... ... %wheel ALL=(ALL) ALL # 找到这一行,表示wheel用户组的用户可以使用sudo ... %wheel ALL=(ALL) NOPASSWD: ALL # 这一行表示无需密码
我们把testuser添加进wheel组,这个组名可以自定义
[root@node4 ~]# usermod -a -G wheel testuser
这样,testuser就可以免密码的使用sudo了
例3:部分授权
前面两个例子都是授予了root的所有权限,如果只想授予部分功能,可以像如下这样
[root@node4 ~]# visudo ... testuser ALL=(root) !/usr/bin/passwd,/usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root ...
授权了testuser可以修改其他用户的密码,但无法修改root的密码
例4:对多个用户授权
如果要对多个用户授权,可以创建别名。这样就不用重复输入那串长长的语句了。
[root@node4 ~]# visudo ... User_Alias ADMPW = user1, user2, user3 Cmnd_Alias ADMPWCOM = !/usr/bin/passwd,/usr/bin/passwd [A-Za-z]*, !/usr/bin/passwd root ADMPW ALL=(root) ADMPWCOM ...
特殊shell
我们可以在创建用户的时候,指定shell为nologin来阻止用户登录
-s /sbin/nologin
比如我们只让某用户有ftp权限,
# useradd -g 用户组 -d 指定默认目录 -M 不创建家目录 禁止登录 用户名
useradd -g ftpgroup -d /opt/ftp/userA -M -s /sbin/nologin userA
这实际上是通过PAM模块实现的
PAM模块
PAM是插入式验证模块的简称。在过去,验证密码是否正确有很多种方式,有了PAM之后,身份验证就只通过PAM统一进行就可以了。
这一段了解即可,详细内容我略过了。
用户信息传递
Linux是可以多用户登录的,那这些同时登录的用户之间,如何进行信息传递呢。
查询命令
-
w或者who,可以列出当前登录用户
[root@node4 ~]# w12:06:58 up 2:34, 2 users, load average: 0.00, 0.01, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.32.1 09:36 2.00s 0.08s 0.00s w testuser pts/1 192.168.32.1 10:30 28:42 0.01s 0.01s -bash
-
lastlog,列出最近登录时间
[root@node4 ~]# lastlog 用户名 端口 来自 最后登陆时间 root pts/1 六 4月 27 10:00:31 +0800 2024 ......
用户信息传递
-
write命令可以在用户之间传递信息
[root@node4 ~]# write testuser pts/1 hello, i am root ## 传入一个中断信号,比如ctrl d 此时testuser会收到 Message from root@node4 on pts/0 at 12:13 ... hello, i am hanayo EOF
-
广播命令wall
[root@node4 ~]# wall "I'wii shutdown right now." [root@node4 ~]# Broadcast message from root@node4 (pts/0) (Sat Apr 27 12:18:10 2024):I'wii shutdown right now.
-
通过邮件mail命令,可以在用户之间发送邮件
小结
本章主要学习了如下内容
- 账号和用户组,UID和GID
- 账号管理基本命令,ACL权限设置
- 身份管理和切换
- 用户之间的信息传递