目录
8.11 Linux修改系统用户信息(usermod命令)
8.12 Linux强制系统用户登陆时修改密码(chage命令)
8.13 Linux删除系统用户(userdel命令)
8.14 Linux查看用户的UID和GID(id命令)
8.15 Linux临时切换用户身份(su命令)
su 和 su - 的区别
8.16 Linux whoami和who am i命令
8.17 Linux添加用户组(groupadd命令)
8.18 Linux修改用户组(groupmod命令)
8.19 Linux删除用户组(groupdel命令)
8.20 Linux将系统用户加入或移除群组(gpasswd命令)
8.21 Linux切换用户的有效群组(newgrp命令)
newgrp命令的底层实现
前面章节介绍了如何利用 useradd 命令添加用户,但如果不小心添错用户信息,后期如何修改呢?
办法有两个,一个是使用 Vim 文本编辑器手动修改涉及用户信息的相关文件(/etc/passwd、/etc/shadow、/etc/group、/etc/gshadow),另一个方法就是使用本节介绍了 usermod 命令,该命令专门用于修改用户信息。
这里一定要分清 useradd 命令和 usermod 命令的区别,前者用于添加用户,当然,添加用户时可以对用户信息进行定制;后者针对与已存在的用户,使用该命令可以修改它们的信息。
usermod 命令的基本格式如下:
[root@localhost ~]#usermod [选项] 用户名
选项:
如果你仔细观察会发现,其实 usermod 命令提供的选项和 useradd 命令的选项相似,因为 usermod 命令就是用来调整使用 useradd 命令添加的用户信息的。
不过,相比 useradd 命令,usermod 命令还多出了几个选项,即 -L 和 -U,作用分别与 passwd 命令的 -l 和-u 相同。需要注意的是,并不是所有的 Linux 发行版都包含这个命令,因此,使用前可以使用 man usermod 命令确定系统是否支持。
此命令对用户的临时锁定,同 passwd 命令一样,都是在 /etc/passwd 文件目标用户的加密密码字段前添加 "!",使密码失效;反之,解锁用户就是将添加的 "!" 去掉。
接下来,给大家分别讲解 usermod 命令几个选项的具体用法。
【例 1】
#锁定用户
[root@localhost ~]# usermod -L lamp
[root@localhost ~]# grep "lamp" /etc/shadow
lamp:!$6$YrPj8g0w$ChRVASybEncU24hkYFqxREH3NnzhAVDJSQLwRwTSbcA2N8UbPD9bBKVQSky xlaMGs/Eg5AQwO.UokOnKqaHFa/:15711:0:99999:7:::
#其实锁定就是在密码字段前加入"!",这时lamp用户就暂时不能登录了
#解锁用户
[root@localhost ~]# usermod -U lamp
[root@localhost ~]# grep "lamp" /etc/shadow
lamp:$6$YrPj8g0w$ChRVASybEncU24hkYFqxREH3NnzhAVDJSQLwRwTSbcA2N8UbPD9bBKVQSkyx laMGs/Eg5AQwO.UokOnKqaHFa/:15711:0:99999:7:::
#取消了密码字段前的 "!"
【例 2】
#把lamp用户加入root组
[root@localhost ~]# usermod -G root lamp
[root@localhost ~]# grep "lamp" /etc/group
root:x:0:lamp
#lamp用户已经加入了root组
lamp:x:501:
【例 3】
#修改用户说明
[root@localhost ~]# usermod -c "test user" lamp
[root@localhost ~]# grep "lamp" /etc/passwd
lamp:x:501:501:test user:/home/lamp:/bin/bash
#查看一下,用户说明已经被修改了
除了 passwd -S
命令可以查看用户的密码信息外,还可以利用 chage 命令,它可以显示更加详细的用户密码信息,并且和 passwd 命令一样,提供了修改用户密码信息的功能。
如果你要修改用户的密码信息,我个人建议,还是直接修改 /etc/shadow 文件更加方便。
首先,我们来看 chage 命令的基本格式:
[root@localhost ~]#chage [选项] 用户名
选项:
【例 1】
#查看一下用户密码状态
[root@localhost ~]# chage -l lamp
Last password change:Jan 06, 2013
Password expires:never
Password inactive :never
Account expires :never
Minimum number of days between password change :0
Maximum number of days between password change :99999
Number of days of warning before password expires :7
读者可能会问,既然直接修改用户密码文件更方便,为什么还要讲解 chage 命令呢?因为 chage 命令除了修改密码信息的功能外,还可以强制用户在第一次登录后,必须先修改密码,并利用新密码重新登陆系统,此用户才能正常使用。
例如,我们创建 lamp 用户,并让其首次登陆系统后立即修改密码,执行命令如下:
#创建新用户 lamp
[root@localhost ~]#useradd lamp
#设置用户初始密码为 lamp
[root@localhost ~]#echo "lamp" | passwd --stdin lamp
#通过chage命令设置此账号密码创建的日期为 1970 年 1 月 1 日(0 就表示这一天),这样用户登陆后就必须修改密码
[root@localhost ~]#chage -d 0 lamp
这样修改完 lamp 用户后,我们尝试用 lamp 用户登陆系统(初始密码也是 lamp):
local host login:lamp
Password: <--输入密码登陆
You are required to change your password immediately (root enforced)
changing password for lamp. <--有一些提示,就是说明 root 强制你登录后修改密码
(current)UNIX password:
#输入旧密码
New password:
Retype new password:
#输入两次新密码
chage 的这个功能常和 passwd 批量初始化用户密码功能合用,且对学校老师帮助比较大,因为老师不想知道学生账号的密码,他们在初次上课时就使用与学号相同的账号和密码给学生,让他们登陆时自行设置他们的密码。这样一来,既能避免学生之间随意使用别人的账号,也能保证学生知道如何修改自己的密码。
userdel 命令功能很简单,就是删除用户的相关数据。此命令只有 root 用户才能使用。
通过前面的学习我们知道,用户的相关数据包含如下几项:
其实,userdel 命令的作用就是从以上文件中,删除与指定用户有关的数据信息。
userdel 命令的语法很简单,基本格式如下:
[root@localhost ~]# userdel -r 用户名
-r 选项表示在删除用户的同时删除用户的家目录。
注意,在删除用户的同时如果不删除用户的家目录,那么家目录就会变成没有属主和属组的目录,也就是垃圾文件。
例如,删除前面章节中创建的 lamp 用户,只需执行如下命令:
[root@localhost ~]# userdel -r lamp
除了使用 userdel 命令删除用户,还可以手动方式删除,毕竟通过前面的学习,我们已经知道与用户相关信息的存储位置。虽然这样做没有实际意义,但对于初学者来说,可以加深对 userdel 命令的理解。
手动删除指定用户的具体操作如下:
#建立新 lamp 用户
[root@localhost ~]# useradd lamp
[root@localhost ~]# passwd lamp
#为 lamp 用户设置密码,由此 lamp 用户才算是创建成功
#下面开始手动删除 lamp
[root@localhost ~]# vi /etc/passwd
lamp:x:501:501::/home/lamp:/bin/bash <--删除此行
#修改用户信息文件,删除lamp用户行
[root@localhost ~]#vi /etc/shadow
lamp:$6$KoOYtcOJ $56Xk9vp3D2vMRBxibNOn.21cVJ9onbW8IHx4WrOx6qBqfGa9U3mjMsGjqYnj L/4t3zt3YxElce2X8rbb12x4a0:15716:0:99999:7::: <--删除此行
#修改影子文件,删除lamp用户密码行,注意,这个文件的权限是000,所以要强制保存
[root@localhost ~]#vi /etc/group
lamp:x:501: <--删除此行
#修改组信息文件,删除lamp群组信息
[root@localhost ~]#vi /etc/gshadow
lamp:!:: <--删除此行
#修改组影子文件,删除lamp群组密码信息。同样注意需要强制保存
[root@localhost ~]# rm -rf /var/spod/mail/lamp #删除用户邮箱
[root@localhost ~]# rm -rf/home/lamp/ #删除用户的家目录
#至此,用户彻底删除,再新建用户lamp。如果可以正常建立,则说明我们手工删除干净了
[root@localhost ~]# useradd lamp
[root@localhost ~]# passwd lamp
#重新建立同名用户,没有报错,说明前面的手工删除是可以完全删除用户的
手动删除用户,仅是为了让读者对 userdel 命令理解地更透彻,实际使用中,使用 userdel 删除用户更方便。
最后需要大家注意的是,如果要删除的用户已经使用过系统一段时间,那么此用户可能在系统中留有其他文件,因此,如果我们想要从系统中彻底的删除某个用户,最好在使用 userdel 命令之前,先通过 find -user 用户名
命令查出系统中属于该用户的文件,然后在加以删除。
id 命令可以查询用户的UID、GID 和附加组的信息。命令比较简单,格式如下:
[root@localhost ~]# id 用户名
【例 1】
[root@localhost ~]# id lamp
uid=501(lamp) gid=501(lamp) groups=501(lamp)
#能看到uid(用户ID)、gid(初始组ID), groups是用户所在组,这里既可以看到初始组,如果有附加组,则也能看到附加组
【例 2】
[root@localhost ~]# usermod -G root lamp
#把用户加入root组
[root@localhost ~]# id lamp
uid=501(lamp) gid=501(lamp) groups=501(lamp),0(root)
#大家发现root组中加入了lamp用户的附加组信息
su 是最简单的用户切换命令,通过该命令可以实现任何身份的切换,包括从普通用户切换为 root 用户、从 root 用户切换为普通用户以及普通用户之间的切换。
普通用户之间切换以及普通用户切换至 root 用户,都需要知晓对方的密码,只有正确输入密码,才能实现切换;从 root 用户切换至其他用户,无需知晓对方密码,直接可切换成功。
su 命令的基本格式如下:
[root@localhost ~]# su [选项] 用户名
选项:
【例 1】
[lamp@localhost ~]$ su -root
密码: <-- 输入 root 用户的密码
#"-"代表连带环境变量一起切换,不能省略
【例 2】
[lamp@localhost ~]$ whoami
lamp
#当前我是lamp
[lamp@localhost ~]$ su - -c "useradd user1" root
密码:
#不切换成root,但是执行useradd命令添加user1用户
[lamp@localhost ~]$ whoami
lamp
#我还是lamp
[lamp@localhost ~]$ grep "user1' /etc/passwd
userl:x:502:504::/home/user1:/bin/bash
#user用户已经添加了
除了像例 2 这样,执行一条命令后用户身份会随即自动切换回来,其他切换用户的方式不会自动切换,只能使用 exit 命令进行手动切换,例如:
[lamp@localhost ~]$ whoami
lamp
#当前我是lamp
[lamp@localhost ~]$ su - lamp1
Password: <-- 输入lamp1用户的密码
#切换至 lamp1 用户的工作环境
[lamp@localhost ~]$ whoami
lamp1
#什么也不做,立即退出切换环境
[lamp1@localhost ~]$ exit
logout
[lamp@localhost ~]$ whoami
lamp
注意,使用 su 命令时,有 - 和没有 - 是完全不同的,- 选项表示在切换用户身份的同时,连当前使用的环境变量也切换成指定用户的。我们知道,环境变量是用来定义操作系统环境的,因此如果系统环境没有随用户身份切换,很多命令无法正确执行。
举个例子,普通用户 lamp 通过 su 命令切换成 root 用户,但没有使用 - 选项,这样情况下,虽然看似是 root 用户,但系统中的 $PATH 环境变量依然是 lamp 的(而不是 root 的),因此当前工作环境中,并不包含 /sbin、/usr/sbin等超级用户命令的保存路径,这就导致很多管理员命令根本无法使用。不仅如此,当 root 用户接受邮件时,会发现收到的是 lamp 用户的邮件,因为环境变量 $MAIL 也没有切换。
初学者可以这样理解它们之间的区别,即有 - 选项,切换用户身份更彻底;反之,只切换了一部分,这会导致某些命令运行出现问题或错误(例如无法使用 service 命令)。
通过下面这个例子,可直观的看到 su 和 su - 的区别:
[lamp@localhost ~]$ whoami
lamp
#查询用户身份,我是lamp
[lamp@localhost ~]$ su root
密码:
<-输入root密码
#切换到root,但是没有切换环境变量。注意:普通用户切换到root需要密码
[root@localhost ~]# env | grep lamp
#查看环境变量,提取包含lamp的行
USER=lamp
#用户名还是lamp,而不是root
PATH=/usr/lib/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/lamp/bin
#命令査找的路径不包含超级用户路径
MAIL=/var/spool/mail/lamp
PWD=/home/lamp
LOGNAME=lamp
#邮箱、主目录、目前用户名还是lamp
可以看到,在不使用 su - 的情况下,虽然用户身份成功切换,但环境变量依旧用的是原用户的,切换并不完整。
whoami 命令和 who am i 命令是不同的 2 个命令,前者用来打印当前执行操作的用户名,后者则用来打印登陆当前 Linux 系统的用户名。
为了能够更好地区分这 2 个命令的功能,给大家举个例子,我们首先使用用户名为“Cyuyan”登陆 Linux 系统,然后执行如下命令:
[Cyuyan@localhost ~]$ whoami
Cyuyan
[Cyuyan@localhost ~]$ who am i
Cyuyan pts/0 2017-10-09 15:30 (:0.0)
在此基础上,使用 su 命令切换到 root 用户下,再执行一遍上面的命令:
[Cyuyan@localhost ~] su - root
[root@localhost ~]$ whoami
root
[root@localhost ~]$ who am i
Cyuyan pts/0 2017-10-09 15:30 (:0.0)
看到了吗?在未切换用户身份之前,whoami 和 who am i 命令的输出是一样的,但使用 su 命令切换用户身份后,使用 whoami 命令打印的是切换后的用户名,而 who am i 命令打印的仍旧是登陆系统时所用的用户名。
执行 whoami 命令,等同于执行 id -un 命令;执行 who am i 命令,等同于执行 who -m 命令。
也就是说,使用 su 或者 sudo 命令切换用户身份,骗得过 whoami,但骗不过 who am i。要解释这背后的运行机制,需要搞清楚什么是实际用户(UID)和有效用户(EUID,即 Effective UID)。
所谓实际用户,指的是登陆 Linux 系统时所使用的用户,因此在整个登陆会话过程中,实际用户是不会发生变化的;而有效用户,指的是当前执行操作的用户,也就是说真正决定权限高低的用户,这个是能够利用 su 或者 sudo 命令进行任意切换的。
一般情况下,实际用户和有效用户是相同的,如果出现用户身份切换的情况,它们会出现差异。需要注意的是,实际用户和有效用户出现差异,切换用户并不是唯一的触发机制,至于其他的触发条件,后续章节会做详细介绍。
那么,whoami 和 who am i通常应用在哪些场景中呢?通常,对那些经常需要切换用户的系统管理员来说,经常需要明确当前使用的是什么身份;另外,对于某些 shell 脚本,或者需要特别的用户才能执行,这时就需要利用 whoami 命令来搞清楚执行它的用户是谁;甚至还有一些 shell 脚本,一定要某个特别用户才能执行,即便使用 su 或者 sudo 命令切换到此身份都不行,此时就需要利用 who am i 来确认。
添加用户组的命令是 groupadd,命令格式如下:
[root@localhost ~]# groupadd [选项] 组名
选项:
使用 groupadd 命令创建新群组非常简单,例如:
[root@localhost ~]# groupadd group1
#添加group1组
[root@localhost ~]# grep "group1" /etc/group
/etc/group:group1:x:502:
/etc/gshadow:group1:!::
groupmod 命令用于修改用户组的相关信息,命令格式如下:
[root@localhost ~]# groupmod [选现] 组名
选项:
例子:
[root@localhost ~]# groupmod -n testgrp group1
#把组名group1修改为testgrp
[root@localhost ~]# grep "testgrp" /etc/group
testgrp:x:502:
#注意GID还是502,但是组名已经改变
不过大家还是要注意,用户名不要随意修改,组名和 GID 也不要随意修改,因为非常容易导致管理员逻辑混乱。如果非要修改用户名或组名,则建议大家先删除旧的,再建立新的。
groupdel 命令用于删除用户组(群组),此命令基本格式为:
[root@localhost ~]#groupdel 组名
通过前面的学习不难猜测出,使用 groupdel 命令删除群组,其实就是删除 /etc/gourp 文件和 /etc/gshadow 文件中有关目标群组的数据信息。
例如,删除前面章节中用 groupadd 命令创建的群组 group1,执行命令如下:
[root@localhost ~]#grep "group1" /etc/group /etc/gshadow
/etc/group:group1:x:505:
/etc/gshadow:group1:!::
[root@localhost ~]#groupdel group1
[root@localhost ~]#grep "group1" /etc/group /etc/gshadow
[root@localhost ~]#
注意,不能使用 groupdel 命令随意删除群组。此命令仅适用于删除那些 "不是任何用户初始组" 的群组,换句话说,如果有群组还是某用户的初始群组,则无法使用 groupdel 命令成功删除。例如:
[root@localhost ~]# useradd temp
#运行如下命令,可以看到 temp 用户建立的同时,还创建了 temp 群组,且将其作为 temp用户的初始组(组ID都是 505)
[root@localhost ~]# grep "temp" /etc/passwd /etc/group /etc/gshadow
/etc/passwd:temp:x:505:505::/home/temp:/bin/bash
/etc/group:temp:x:505:
/etc/gshadow:temp:!::
#下面尝试删除 temp 群组
[root@localhost ~]# groupdel temp
groupdel:cannot remove the primary group of user 'temp'
可以看到,groupdel 命令删除 temp 群组失败,且提示“不能删除 temp 用户的初始组”。如果一定要删除 temp 群组,要么修改 temp 用户的 GID,也就是将其初始组改为其他群组,要么先删除 temp 用户。
切记,虽然我们已经学了如何手动删除群组数据,但胡乱地删除群组可能会给其他用户造成不小的麻烦,因此更改文件数据要格外慎重。
为了避免系统管理员(root)太忙碌,无法及时管理群组,我们可以使用 gpasswd 命令给群组设置一个群组管理员,代替 root 完成将用户加入或移出群组的操作。
gpasswd 命令的基本格式如下:
[root@localhost ~]# gpasswd 选项 组名
表 1 详细介绍了此命令提供的各种选项以及功能。
选项 | 功能 |
---|---|
选项为空时,表示给群组设置密码,仅 root 用户可用。 | |
-A user1,... | 将群组的控制权交给 user1,... 等用户管理,也就是说,设置 user1,... 等用户为群组的管理员,仅 root 用户可用。 |
-M user1,... | 将 user1,... 加入到此群组中,仅 root 用户可用。 |
-r | 移除群组的密码,仅 root 用户可用。 |
-R | 让群组的密码失效,仅 root 用户可用。 |
-a user | 将 user 用户加入到群组中。 |
-d user | 将 user 用户从群组中移除。 |
从表 1 可以看到,除 root 可以管理群组外,可设置多个普通用户作为群组的管理员,但也只能做“将用户加入群组”和“将用户移出群组”的操作。
【例 1】
#创建新群组 group1,并将群组交给 lamp 管理
[root@localhost ~]# groupadd group1 <-- 创建群组
[root@localhost ~]# gpasswd group1 <-- 设置密码吧!
Changing the password for group group1
New Password:
Re-enter new password:
[root@localhost ~]# gpasswd -A lamp group1 <==加入群组管理员为 lamp
[root@localhost ~]# grep "group1" /etc/group /etc/gshadow
/etc/group:group1:x:506:
/etc/gshadow:group1:$1$I5ukIY1.$o5fmW.cOsc8.K.FHAFLWg0:lamp:
可以看到,此时 lamp 用户即为 group1 群组的管理员。
【例 2】
#以lamp用户登陆系统,并将用户 lamp 和 lamp1 加入group1群组。
[lamp@localhost ~]#gpasswd -a lamp group1
[lamp@localhost ~]#gpasswd -a lamp1 group1
[lamp@localhost ~]#grep "group1" /etc/group
group1:x:506:lamp,lamp1
前面讲过,使用 usermod -G
命令也可以将用户加入群组,但会产生一个问题,即使用此命令将用户加入到新的群组后,该用户之前加入的那些群组都将被清空。例如:
#新创建一个群组group2
[root@localhost ~]# groupadd group2
[root@localhost ~]# usermod -G group2 lamp
[root@localhost ~]# grep "group2" /etc/group
group2:x:509:lamp
[root@localhost ~]# grep "group1" /etc/group
group1:x:506:lamp1
对比例 2 可以发现,虽然使用 usermod 命令成功地将 lamp 用户加入在 group2 群组中,但 lamp 用户原本在 group1 群组中,此时却被移出,这就是使用 usermod 命令造成的。
因此,将用户加入或移出群组,最好使用 gpasswd 命令。
我们知道,每个用户可以属于一个初始组(用户是这个组的初始用户),也可以属于多个附加组(用户是这个组的附加用户)。既然用户可以属于这么多用户组,那么用户在创建文件后,默认生效的组身份是哪个呢?
当然是初始用户组的组身份生效,因为初始组是用户一旦登陆就获得的组身份。也就是说,用户的有效组默认是初始组,因此所创建文件的属组是用户的初始组。那么,既然用户属于多个用户组,能不能改变用户的初始组呢?使用命令 newgrp 就可以。
newgrp 命令可以从用户的附加组中选择一个群组,作为用户新的初始组。此命令的基本格式如下:
[root@localhost ~]# newgrp 组名
下面,我们通过一个实例,讲解此命令的具体用法和功能:
[root@localhost ~]# groupadd group1
[root@localhost ~]# groupadd group2
[root@localhost ~]# groupadd group3
[root@localhost ~]# useradd -g group1 -G group2,group3 user1
#由于指定了初始组,因此不会在创建 user1 默认群组
[root@localhost ~]# more /etc/group | grep user1
group2:x:501:user1
group3:x:502:user1
[root@localhost ~]# passwd user1
Changing password for user user1.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
#切换至 user1 用户
[root@localhost ~]# su - user1
[root@localhost ~]# whoami
user1
#使用 newgrp 命令一边切换 user1 的初始组,一边创建文件
[root@localhost ~]# mkdir user1_doc
[root@localhost ~]# newgrp group2
[root@localhost ~]# mkdir user2_doc
[root@localhost ~]# newgrp group3
[root@localhost ~]# mkdir user3_doc
#查看各文件的详细信息
[root@localhost ~]# ll
total 12
drwxr-xr-x 2 user1 group1 4096 Oct 24 01:18 user1_doc
drwxr-xr-x 2 user1 group2 4096 Oct 24 01:18 user2_doc
drwxr-xr-x 2 user1 group3 4096 Oct 24 01:19 user3_doc
可以看到,通过使用 newgrp 命令切换用户的初始组,所创建的文件各自属于不同的群组,这就是 newgrp 所发挥的作用,即通过切换附加组成为新的初始组,从而让用户获得使用各个附加组的权限。
其实,newgrp 命令每一次切换用户的初始组,该用户都会以另外一个 shell(新进程,也可以说是子进程)登陆,只不过在新 shell 上登陆的该用户,其初始组改变了而已。
以上实例中,通过添加 shell 内置命令 "echo $$" 就可以发现,每次使用 newgrp 命令,都会切换到一个新的进程。
在本节实例中,使用 newgrp 命令切换用户初始组的整个过程,如图 1 所示:
可以看到,每一次使用 newgrp 切换用户的初始组,用户都会切换到一个新的子 shell 中,如图 1 中,user1 用户的初始组从最初的 group1,切换成了 group2,再切换成 group3。
当然,如果你想回到原本的环境,需要通过 exit 命令不断回退到当前进程的父进程,最终才能回到初始组为 group1 时的 user1 运行的 shell 中。