第一章:用户和用户组

1.1 用户和用户组

Linux 是多用户多任务操作系统,换句话说,Linux 系统支持多个用户在同一时间内登陆,不同用户可以执行不同的任务,并且互不影响。
例如,某台 Linux 服务器上有 4 个用户,分别是 root、www、ftp 和 mysql,在同一时间内,root 用户可能在查看系统日志、管理维护系统;www 用户可能在修改自己的网页程序;ftp 用户可能在上传软件到服务器;mysql 用户可能在执行自己的 SQL 查询,每个用户互不干扰,有条不紊地进行着自己的工作。与此同时,每个用户之间不能越权访问,比如 www 用户不能执行 mysql 用户的 SQL 查询操作,ftp 用户也不能修改 www 用户的网页程序。
不同用户具有不问的权限,毎个用户在权限允许的范围内完成不间的任务,Linux 正是通过这种权限的划分与管理,实现了多用户多任务的运行机制。
因此,如果要使用 Linux 系统的资源,就必须向系统管理员申请一个账户,然后通过这个账户进入系统(账户和用户是一个概念)。通过建立不同属性的用户,一方面可以合理地利用和控制系统资源,另一方面也可以帮助用户组织文件,提供对用户文件的安全性保护。
每个用户都有唯一的用户名和密码。在登录系统时,只有正确输入用户名和密码,才能进入系统和自己的主目录。
用户组是具有相同特征用户的逻辑集合。简单的理解,有时我们需要让多个用户具有相同的权限,比如查看、修改某一个文件的权限,一种方法是分别对多个用户进行文件访问授权,如果有 10 个用户的话,就需要授权 10 次,那如果有 100、1000 甚至更多的用户呢?
显然,这种方法不太合理。最好的方式是建立一个组,让这个组具有查看、修改此文件的权限,然后将所有需要访问此文件的用户放入这个组中。那么,所有用户就具有了和组一样的权限,这就是用户组。
将用户分组是 Linux 系统中对用户进行管理及控制访问权限的一种手段,通过定义用户组,很多程序上简化了对用户的管理工作。

1.2 Linux用户和组的关系

用户和用户组的对应关系有以下 4 种:

  1. 一对一:一个用户可以存在一个组中,是组中的唯一成员;
  2. 一对多:一个用户可以存在多个用户组中,此用户具有这多个组的共同权限;
  3. 多对一:多个用户可以存在一个组中,这些用户具有和组相同的权限;
  4. 多对多:多个用户可以存在多个组中,也就是以上 3 种关系的扩展。

用户和组之间的关系可以用图 1 来表示:
image.png

1.3 id 命令:查看用户的 UID 和 GID

登录 Linux 系统时,虽然输入的是自己的用户名和密码,但其实 Linux 并不认识你的用户名称,它只认识用户名对应的 ID 号(也就是一串数字)。Linux 系统将所有用户的名称与 ID 的对应关系都存储在 /etc/passwd 文件中。
说白了,用户名并无实际作用,仅是为了方便用户的记忆而已。
要论证 “Linux系统不认识用户名” 也很简单,在前面章节,我们曾经在网络上下载过 .tar.gz 或 .tar.bz2 格式的文件,在解压缩之后的文件中,你会发现文件拥有者的属性显示的是一串数字,这很正常,就是因为系统只认识代表你身份的 ID,这串数字就是用户的 ID(UID)号。
Linux 系统中,每个用户的 ID 细分为 2 种,分别是用户 ID(User ID,简称 UID)和组 ID(Group ID,简称 GID),这与文件有拥有者和拥有群组两种属性相对应(如图 1 所示)。
image.png
图 1 文件的拥有者和群组属性
从图 1 中可以看到,该文件的拥有者是超级管理员 root,拥有群组也是 root。读者可能会问,既然 Linux 系统不认识用户名,文件是如何判别它的拥有者名称和群组名称的呢?
每个文件都有自己的拥有者 ID 和群组 ID,当显示文件属性时,系统会根据 /etc/passwd 和 /etc/group 文件中的内容,分别找到 UID 和 GID 对应的用户名和群组名,然后显示出来。
/etc/passwd 文件和 /etc/group 文件,后续文章会做详细讲解,这里只需要知道,在 /etc/passwd 文件中,利用 UID 可以找到对应的用户名;在 /etc/group 文件中,利用 GID 可以找到对应的群组名。
做个小实验,笔者所用的 Linux 系统中,常用的有两个账户,分别为 root 超级管理员账户和 lintcode 普通账户,我们先使用 root 账号登陆并 Vim /etc/passwd,在该文件中找到 lintcode 账户并将其 UID 随意改一个数字,这时当你查看普通账户拥有的文件时,你会发现所有文件的拥有者不再是 lintcode,而是数字。
具体执行过程如下所示:

  1. #查看系统中是否存在lintcode这个用户
  2. [root@livecd ~]#grep 'lintcode' /etc/passwd
  3. lintcode:x:500:500:lintcode:/home/centoslive:/bin/bash
  4. [root@livecd ~]#ll -d /home/centoslive
  5. drwx------. 23 lintcode centoslive 4096 Apr 9 09:37 /home/centoslive
  6. [root@livecd ~]#vim /etc.passwd
  7. #修改lintcode账户中的UID(第一个 500)为 2000
  8. [root@livecd ~]#ll -d /home/centoslive
  9. drwx------. 23 500 centoslive 4096 Apr 9 09:37 /home/centoslive
  10. #可以看到,之前的 lintcode 变为了 500,因为修改了UID,导致 500 找不到对应的账号,因此显示数字
  11. #记得最后将其再手动改正过来
  12. [root@livecd ~]#vim /etc.passwd
  13. #修改lintcode账户中的UID从 2000 改为 500

由于 lintcode 账户的 UID 已经改为 2000,但其 home 目录却记录的是 500,会导致此用户再次登录时无法进入自己的 home 目录。
注意,本节为了说明 ID 和用户名的对应关系,所以才将 /etc/passwd 文件中用户的 UID 做了更改。此操作很可能会导致某些程序无法进行,因此 /etc/passwd 文件不能随意修改。

1.3.1 语法格式

id 命令可以查询用户的 UID、GID 和附加组的信息。命令比较简单,格式如下:
**_[root__@localhost__ ~]__# id 用户名_**

1.3.2 例子

例 1

  1. [root@localhost ~]# id lamp
  2. uid=501(lamp) gid=501(lamp) groups=501(lamp)
  3. #能看到uid(用户ID)、gid(初始组ID), groups是用户所在组,这里既可以看到初始组,如果有附加组,则也能看到附加组

例 2

  1. [root@localhost ~]# usermod -G root lamp
  2. #把用户加入root组
  3. [root@localhost ~]# id lamp
  4. uid=501(lamp) gid=501(lamp) groups=501(lamp),0(root)
  5. #大家发现root组中加入了lamp用户的附加组信息

1.4 whoami 和 who am i

whoami 命令和 who am i 命令是不同的 2 个命令,前者用来打印当前执行操作的用户名,后者则用来打印登录当前 Linux 系统的用户名。
为了能够更好地区分这 2 个命令的功能,给大家举个例子,我们首先使用用户名为 linghuchong 登录 Linux 系统,然后执行如下命令:

  1. [linghuchong@localhost ~]$ whoami
  2. linghuchong
  3. [linghuchong@localhost ~]$ who am i
  4. linghuchong pts/0 2021-06-28 15:30 (:0.0)

在此基础上,使用 su 命令切换到 root 用户下,再执行一遍上面的命令:

  1. [linghuchong@localhost ~] su - root
  2. [root@localhost ~]$ whoami
  3. root
  4. [root@localhost ~]$ who am i
  5. linghuchong pts/0 2021-06-28 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 来确认。换到此身份都不行,此时就需要利用 who am i 来确认。

1.5 passwd 命令:修改用户密码

学习 useradd 命令我们知道,使用此命令创建新用户时,并没有设定用户密码,因此还无法用来登陆系统,本节就来学习 passwd 密码配置命令。

1.5.1 语法格式

passwd 命令的基本格式如下:
**_[root@localhost ~]#passwd [选项] 用户名_**
选项:

  • -S:查询用户密码的状态,也就是 /etc/shadow 文件中此用户密码的内容。仅 root 用户可用;
  • -l:暂时锁定用户,该选项会在 /etc/shadow 文件中指定用户的加密密码串前添加 “!”,使密码失效。仅 root 用户可用;
  • -u:解锁用户,和 -l 选项相对应,也是只能 root 用户使用;
  • —stdin:可以将通过管道符输出的数据作为用户的密码。主要在批量添加用户时使用;
  • -n 天数:设置该用户修改密码后,多长时间不能再次修改密码,也就是修改 /etc/shadow 文件中各行密码的第 4 个字段;
  • -x 天数:设置该用户的密码有效期,对应 /etc/shadow 文件中各行密码的第 5 个字段;
  • -w 天数:设置用户密码过期前的警告天数,对于 /etc/shadow 文件中各行密码的第 6 个字段;
  • -i 日期:设置用户密码失效日期,对应 /etc/shadow 文件中各行密码的第 7 个字段。

例如,我们使用 root 账户修改 lamp 普通用户的密码,可以使用如下命令:

  1. [root@localhost ~]#passwd lamp
  2. Changing password for user lamp.
  3. New password: <==直接输入新的口令,但屏幕不会有任何反应
  4. BAD PASSWORD: it is WAY too short <==口令太简单或过短的错误!这里只是警告信息,输入的密码依旧能用
  5. Retype new password: <==再次验证输入的密码,再输入一次即可
  6. passwd: all authentication tokens updated successfully. <==提示修改密码成功

当然,也可以使用 passwd 命令修改当前系统已登录用户的密码,但要注意的是,需省略掉 “选项” 和 “用户名”。例如,我们登陆 lamp 用户,并使用 passwd 命令修改 lamp 的登陆密码,执行过程如下:

  1. [root@localhost ~]#passwd
  2. #passwd直接回车代表修改当前用户的密码
  3. Changing password for user vbird2.
  4. Changing password for vbird2
  5. (current) UNIX password: <==这里输入『原有的旧口令』
  6. New password: <==这里输入新口令
  7. BAD PASSWORD: it is WAY too short <==口令检验不通过,请再想个新口令
  8. New password: <==这里再想个来输入吧
  9. Retype new password: <==通过口令验证!所以重复这个口令的输入
  10. passwd: all authentication tokens updated successfully. <==成功修改用户密码

注意,普通用户只能使用 passwd 命令修改自己的密码,而不能修改其他用户的密码。
可以看到,与使用 root 账户修改普通用户的密码不同,普通用户修改自己的密码需要先输入自己的旧密码,只有旧密码输入正确才能输入新密码。不仅如此,此种修改方式对密码的复杂度有严格的要求,新密码太短、太简单,都会被系统检测出来并禁止用户使用。
很多Linux 发行版为了系统安装,都使用了 PAM 模块进行密码的检验,设置密码太短、与用户名相同、是常见字符串等,都会被 PAM 模块检查出来,从而禁止用户使用此类密码。有关 PAM 模块,后续章节会进行详细介绍。
而使用 root 用户,无论是修改普通用户的密码,还是修改自己的密码,都可以不遵守 PAM 模块设定的规则,就比如我刚刚给 lamp 用户设定的密码是 “123”,系统虽然会提示密码过短和过于简单,但依然可以设置成功。当然,在实际应用中,就算是 root 身份,在设定密码时也要严格遵守密码规范,因为只有好的密码规范才是服务器安全的基础。
passwd 命令还提供了一些选项,接下来给大家介绍各个选项的具体用法。

1.5.2 例子

例 1

  1. #查看用户密码的状态
  2. [root@localhost ~]# passwd -S lamp
  3. lamp PS 2013-01-06 0 99999 7 -1 (Password set, SHA512 crypt.)
  4. #上面这行代码的意思依次是:用户名 密码 设定时间(2013*01-06) 密码修改间隔时间(0) 密码有效期(99999) 警告时间(7) 密码不失效(-1),密码已使用

-S 选项会显示出密码状态,这里的密码修改间隔时间、密码有效期、警告时间、密码宽限时间其实分别是 /etc/shadow 文件的第四、五、六、七个字段的内容。 当然,passwd 命令是可以通过命令选项修改这几个字段的值的,例如:

  1. #锁定 lamp 用户
  2. [root@localhost ~]# passwd -I lamp
  3. Locking password for user lamp.
  4. passwd:Successg
  5. #用"-S"选项査看状态,很清楚地提示密码已被锁定
  6. [root@localhost ~]# passwd -S lamp
  7. lamp LK 2013-01-06 0 99999 7 -1 (Password locked.)
  8. [root@localhost ~]# grep "lamp" /etc/shadow
  9. lamp:!! $6$ZTq7o/9o $lj07iZ0bzW.D1zBa9CsY43d04onskUCzjwiFMNt8PX4GXJoHX9zA1S C9.i Yzh9LZA4fEM2lg92hM9w/p6NS50.:15711:0:99999:7:::
  10. #可以看到,锁定其实就是在加密密码之前加入了"!!",让密码失效而已

这里显示 SHA512 为密码加密方式,CentOS 6.3 加密方式已经从 MD5 加密更新到 SHA512 加密,我们不用了解具体的加密算法,只要知道这种加密算法更加可靠和先进就足够了。

例 2

锁定 lamp 用户 [root@localhost ~]# passwd -I lamp Locking password for user lamp. passwd:Successg #用”-S”选项査看状态,很清楚地提示密码已被锁定 [root@localhost ~]# passwd -S lamp lamp LK 2013-01-06 0 99999 7 -1 (Password locked.) [root@localhost ~]# grep “lamp” /etc/shadow lamp:!! $6$ZTq7o/9o $lj07iZ0bzW.D1zBa9CsY43d04onskUCzjwiFMNt8PX4GXJoHX9zA1S C9.i Yzh9LZA4fEM2lg92hM9w/p6NS50.:15711:0:99999:7::: #可以看到,锁定其实就是在加密密码之前加入了”!!”,让密码失效而已
暂时锁定 lamp 用户后,此用户就不能登录系统了。那么,怎么解锁呢?也一样简单,使用如下命令即可:

  1. #解锁 lamp 用户
  2. [root@localhost ~]# passwd -u lamp
  3. Unlocking password for user lamp.
  4. passwd:Success
  5. [root@localhost ~]# passwd -S lamp
  6. lamp PS 2013-01-06 0 99999 7 -1 (Password set, SHA512 crypt.)
  7. #可以看到,锁定状态消失
  8. [root@localhost ~]# grep "lamp" /etc/shadow
  9. lamp: $6$ZTq7cV9o $lj07iZ0bzW.D1zBa9CsY43d04onskUCzjwiFMNt8PX4GXJoHX9zA1S C9.iYz h9LZA4fEM2lg92hM9w/p6NS50.:15711:0:99999:7:::
  10. #密码前面的 "!!" 删除了

例 3

  1. #调用管道符,给 lamp 用户设置密码 "123"
  2. [root@localhost ~]# echo "123" | passwd --stdin lamp
  3. Changing password for user lamp.
  4. passwd: all authentication tokens updated successfully.

为了方便系统管理,passwd 命令提供了 —stdin 选项,用于批量给用户设置初始密码。
使用此方式批量给用户设置初始密码,当然好处就是方便快捷,但需要注意的是,这样设定的密码会把密码明文保存在历史命令中,如果系统被攻破,别人可以在 /root/.bash_history 中找到设置密码的这个命令,存在安全隐患。
因此,读者如果使用这种方式修改密码,那么应该记住两件事情:第一,手工清除历史命令;第二,强制这些新添加的用户在第一次登录时必须修改密码。
注意,并非所有 Linux 发行版都支持使用此选项,使用之前可以使用 man passwd 命令确认当前系统是否支持。

1.6 usermod 命令:修改用户信息

如果不小心添错用户信息,后期如何修改呢?
办法有两个,一个是使用 Vim 文本编辑器手动修改涉及用户信息的相关文件(/etc/passwd、/etc/shadow、/etc/group、/etc/gshadow),另一个方法就是使用本节介绍了 usermod 命令,该命令专门用于修改用户信息。
这里一定要分清 useradd 命令和 usermod 命令的区别,前者用于添加用户,当然,添加用户时可以对用户信息进行定制;后者针对与已存在的用户,使用该命令可以修改它们的信息。

1.6.1 语法格式

usermod 命令的基本格式如下:
**_[root@localhost ~]#usermod [选项] 用户名_**
选项:

  • -c 用户说明:修改用户的说明信息,即修改 /etc/passwd 文件目标用户信息的第 5 个字段;
  • -d 主目录:修改用户的主目录,即修改 /etc/passwd 文件中目标用户信息的第 6 个字段,需要注意的是,主目录必须写绝对路径;
  • -e 日期:修改用户的失效曰期,格式为 “YYYY-MM-DD”,即修改 /etc/shadow 文件目标用户密码信息的第 8 个字段;
  • -g 组名:修改用户的初始组,即修改 /etc/passwd 文件目标用户信息的第 4 个字段(GID);
  • -u UID:修改用户的UID,即修改 /etc/passwd 文件目标用户信息的第 3 个字段(UID);
  • -G 组名:修改用户的附加组,其实就是把用户加入其他用户组,即修改 /etc/group 文件;
  • -l 用户名:修改用户名称;
  • -L:临时锁定用户(Lock);
  • -U:解锁用户(Unlock),和 -L 对应;
  • -s shell:修改用户的登录 Shell,默认是 /bin/bash。

如果你仔细观察会发现,其实 usermod 命令提供的选项和 useradd 命令的选项相似,因为 usermod 命令就是用来调整使用 useradd 命令添加的用户信息的。
不过,相比 useradd 命令,usermod 命令还多出了几个选项,即 -L 和 -U,作用分别与 passwd 命令的 -l 和-u 相同。需要注意的是,并不是所有的 Linux 发行版都包含这个命令,因此,使用前可以使用 man usermod 命令确定系统是否支持。
此命令对用户的临时锁定,同 passwd 命令一样,都是在 /etc/passwd 文件目标用户的加密密码字段前添加 !,使密码失效;反之,解锁用户就是将添加的 ! 去掉。

1.6.2 例子

例 1

  1. #锁定用户
  2. [root@localhost ~]# usermod -L lamp
  3. [root@localhost ~]# grep "lamp" /etc/shadow
  4. lamp:!$6$YrPj8g0w$ChRVASybEncU24hkYFqxREH3NnzhAVDJSQLwRwTSbcA2N8UbPD9bBKVQSky xlaMGs/Eg5AQwO.UokOnKqaHFa/:15711:0:99999:7:::
  5. #其实锁定就是在密码字段前加入"!",这时lamp用户就暂时不能登录了
  6. #解锁用户
  7. [root@localhost ~]# usermod -U lamp
  8. [root@localhost ~]# grep "lamp" /etc/shadow
  9. lamp:$6$YrPj8g0w$ChRVASybEncU24hkYFqxREH3NnzhAVDJSQLwRwTSbcA2N8UbPD9bBKVQSkyx laMGs/Eg5AQwO.UokOnKqaHFa/:15711:0:99999:7:::
  10. #取消了密码字段前的 "!"

例 2

  1. #把lamp用户加入root组
  2. [root@localhost ~]# usermod -G root lamp
  3. [root@localhost ~]# grep "lamp" /etc/group
  4. root:x:0:lamp
  5. #lamp用户已经加入了root组
  6. lamp:x:501:

例 3

  1. #修改用户说明
  2. [root@localhost ~]# usermod -c "test user" lamp
  3. [root@localhost ~]# grep "lamp" /etc/passwd
  4. lamp:x:501:501:test user:/home/lamp:/bin/bash
  5. #查看一下,用户说明已经被修改了

1.7 chage 用法详解:修改用户密码状态

除了 passwd -S 命令可以查看用户的密码信息外,还可以利用 chage 命令,它可以显示更加详细的用户密码信息,并且和 passwd 命令一样,提供了修改用户密码信息的功能。
如果你要修改用户的密码信息,我个人建议,还是直接修改 /etc/shadow 文件更加方便。

1.7.1 语法格式

chage 命令的基本格式如下:
**_[root@localhost ~]#chage [选项] 用户名_**
选项:

  • -l:列出用户的详细密码状态;
  • -d 日期:修改 /etc/shadow 文件中指定用户密码信息的第 3 个字段,也就是最后一次修改密码的日期,格式为 YYYY-MM-DD;
  • -m 天数:修改密码最短保留的天数,也就是 /etc/shadow 文件中的第 4 个字段;
  • -M 天数:修改密码的有效期,也就是 /etc/shadow 文件中的第 5 个字段;
  • -W 天数:修改密码到期前的警告天数,也就是 /etc/shadow 文件中的第 6 个字段;
  • -i 天数:修改密码过期后的宽限天数,也就是 /etc/shadow 文件中的第 7 个字段;
  • -E 日期:修改账号失效日期,格式为 YYYY-MM-DD,也就是 /etc/shadow 文件中的第 8 个字段。

    1.7.2 例子

    例 1

    1. #查看一下用户密码状态
    2. [root@localhost ~]# chage -l lamp
    3. Last password change:Jan 06, 2013
    4. Password expires:never
    5. Password inactive :never
    6. Account expires :never
    7. Minimum number of days between password change :0
    8. Maximum number of days between password change :99999
    9. Number of days of warning before password expires :7

    读者可能会问,既然直接修改用户密码文件更方便,为什么还要讲解 chage 命令呢?因为 chage 命令除了修改密码信息的功能外,还可以强制用户在第一次登录后,必须先修改密码,并利用新密码重新登陆系统,此用户才能正常使用。
    例如,我们创建 lamp 用户,并让其首次登陆系统后立即修改密码,执行命令如下:

    1. #创建新用户 lamp
    2. [root@localhost ~]#useradd lamp
    3. #设置用户初始密码为 lamp
    4. [root@localhost ~]#echo "lamp" | passwd --stdin lamp
    5. #通过chage命令设置此账号密码创建的日期为 1970 年 1 月 1 日(0 就表示这一天),这样用户登陆后就必须修改密码
    6. [root@localhost ~]#chage -d 0 lamp

    这样修改完 lamp 用户后,我们尝试用 lamp 用户登陆系统(初始密码也是 lamp):

    1. local host login:lamp
    2. Password: <--输入密码登陆
    3. You are required to change your password immediately (root enforced)
    4. changing password for lamp. <--有一些提示,就是说明 root 强制你登录后修改密码
    5. (current)UNIX password:
    6. #输入旧密码
    7. New password:
    8. Retype new password:
    9. #输入两次新密码

    chage 的这个功能常和 passwd 批量初始化用户密码功能合用,且对学校老师帮助比较大,因为老师不想知道学生账号的密码,他们在初次上课时就使用与学号相同的账号和密码给学生,让他们登陆时自行设置他们的密码。这样一来,既能避免学生之间随意使用别人的账号,也能保证学生知道如何修改自己的密码。

    1.8 userdel 命令详解:删除用户

    userdel 命令功能很简单,就是删除用户的相关数据。此命令只有 root 用户才能使用。
    通过前面的学习我们知道,用户的相关数据包含如下几项:

  • 用户基本信息:存储在 /etc/passwd 文件中;

  • 用户密码信息:存储在 /etc/shadow 文件中;
  • 用户群组基本信息:存储在 /etc/group 文件中;
  • 用户群组信息信息:存储在 /etc/gshadow 文件中;
  • 用户个人文件:主目录默认位于 /home/用户名,邮箱位于 /var/spool/mail/用户名。

其实,userdel 命令的作用就是从以上文件中,删除与指定用户有关的数据信息。

1.8.1 语法格式

userdel 命令的基本格式如下:
**_[root__@localhost__ ~]__# userdel -r 用户名_**
-r 选项表示在删除用户的同时删除用户的家目录。
注意,在删除用户的同时如果不删除用户的家目录,那么家目录就会变成没有属主和属组的目录,也就是垃圾文件。

1.8.2 例子

例 1

删除前面章节中创建的 lamp 用户,只需执行如下命令:
**_[root__@localhost__ ~]__# userdel -r lamp_**
除了使用 userdel 命令删除用户,还可以手动方式删除,毕竟通过前面的学习,我们已经知道与用户相关信息的存储位置。虽然这样做没有实际意义,但对于初学者来说,可以加深对 userdel 命令的理解。
手动删除指定用户的具体操作如下:

  1. #建立新 lamp 用户
  2. [root@localhost ~]# useradd lamp
  3. [root@localhost ~]# passwd lamp
  4. #为 lamp 用户设置密码,由此 lamp 用户才算是创建成功
  5. #下面开始手动删除 lamp
  6. [root@localhost ~]# vi /etc/passwd
  7. lamp:x:501:501::/home/lamp:/bin/bash <--删除此行
  8. #修改用户信息文件,删除lamp用户行
  9. [root@localhost ~]#vi /etc/shadow
  10. lamp:$6$KoOYtcOJ $56Xk9vp3D2vMRBxibNOn.21cVJ9onbW8IHx4WrOx6qBqfGa9U3mjMsGjqYnj L/4t3zt3YxElce2X8rbb12x4a0:15716:0:99999:7::: <--删除此行
  11. #修改影子文件,删除lamp用户密码行,注意,这个文件的权限是000,所以要强制保存
  12. [root@localhost ~]#vi /etc/group
  13. lamp:x:501: <--删除此行
  14. #修改组信息文件,删除lamp群组信息
  15. [root@localhost ~]#vi /etc/gshadow
  16. lamp:!:: <--删除此行
  17. #修改组影子文件,删除lamp群组密码信息。同样注意需要强制保存
  18. [root@localhost ~]# rm -rf /var/spod/mail/lamp #删除用户邮箱
  19. [root@localhost ~]# rm -rf/home/lamp/ #删除用户的家目录
  20. #至此,用户彻底删除,再新建用户lamp。如果可以正常建立,则说明我们手工删除干净了
  21. [root@localhost ~]# useradd lamp
  22. [root@localhost ~]# passwd lamp
  23. #重新建立同名用户,没有报错,说明前面的手工删除是可以完全删除用户的

手动删除用户,仅是为了让读者对 userdel 命令理解地更透彻,实际使用中,使用 userdel 删除用户更方便。
最后需要大家注意的是,如果要删除的用户已经使用过系统一段时间,那么此用户可能在系统中留有其他文件,因此,如果我们想要从系统中彻底的删除某个用户,最好在使用 userdel 命令之前,先通过 find -user 用户名 命令查出系统中属于该用户的文件,然后在加以删除。

1.9 su 命令:用户间切换包含

su 是最简单的用户切换命令,通过该命令可以实现任何身份的切换,包括从普通用户切换为 root 用户、从 root 用户切换为普通用户以及普通用户之间的切换。
普通用户之间切换以及普通用户切换至 root 用户,都需要知晓对方的密码,只有正确输入密码,才能实现切换;从 root 用户切换至其他用户,无需知晓对方密码,直接可切换成功。

1.9.1 语法格式

su 命令的基本格式如下:
**_[root@localhost ~]# su [选项] 用户名_**
选项:

  • -:当前用户不仅切换为指定用户的身份,同时所用的工作环境也切换为此用户的环境(包括 PATH 变量、MAIL 变量等),使用 - 选项可省略用户名,默认会切换为 root 用户。
  • -l:同 - 的使用类似,也就是在切换用户身份的同时,完整切换工作环境,但后面需要添加欲切换的使用者账号。
  • -p:表示切换为指定用户的身份,但不改变当前的工作环境(不使用切换用户的配置文件)。
  • -m:和 -p 一样;
  • -c :仅切换用户执行一次命令,执行后自动切换回来,该选项后通常会带有要执行的命令。

    1.9.2 例子

    例 1

    1. [lamp@localhost ~]$ su -root
    2. 密码: <-- 输入 root 用户的密码
    3. #"-"代表连带环境变量一起切换,不能省略

    例 2

    1. [lamp@localhost ~]$ whoami
    2. lamp
    3. #当前我是lamp
    4. [lamp@localhost ~]$ su - -c "useradd user1" root
    5. 密码:
    6. #不切换成root,但是执行useradd命令添加user1用户
    7. [lamp@localhost ~]$ whoami
    8. lamp
    9. #我还是lamp
    10. [lamp@localhost ~]$ grep "user1' /etc/passwd
    11. userl:x:502:504::/home/user1:/bin/bash
    12. #user用户已经添加了
    除了像例 2 这样,执行一条命令后用户身份会随即自动切换回来,其他切换用户的方式不会自动切换,只能使用 exit 命令进行手动切换,例如:
    1. [lamp@localhost ~]$ whoami
    2. lamp
    3. #当前我是lamp
    4. [lamp@localhost ~]$ su - lamp1
    5. Password: <--输入lamp1用户的密码
    6. #切换至 lamp1 用户的工作环境
    7. [lamp@localhost ~]$ whoami
    8. lamp1
    9. #什么也不做,立即退出切换环境
    10. [lamp1@localhost ~]$ exit
    11. logout
    12. [lamp@localhost ~]$ whoami
    13. lamp

    1.9.3 su 和 su - 的区别

    注意,使用 su 命令时,有 - 和没有 - 是完全不同的,- 选项表示在切换用户身份的同时,连当前使用的环境变量也切换成指定用户的。我们知道,环境变量是用来定义操作系统环境的,因此如果系统环境没有随用户身份切换,很多命令无法正确执行。
    举个例子,普通用户 lamp 通过 su 命令切换成 root 用户,但没有使用 - 选项,这样情况下,虽然看似是 root 用户,但系统中的 $PATH 环境变量依然是 lamp 的(而不是 root 的),因此当前工作环境中,并不包含 /sbin、/usr/sbin 等超级用户命令的保存路径,这就导致很多管理员命令根本无法使用。不仅如此,当 root 用户接受邮件时,会发现收到的是 lamp 用户的邮件,因为环境变量 $MAIL 也没有切换。
    初学者可以这样理解它们之间的区别,即有 - 选项,切换用户身份更彻底;反之,只切换了一部分,这会导致某些命令运行出现问题或错误(例如无法使用 service 命令)。
    通过下面这个例子,可直观的看到 su 和 su - 的区别:
    1. [lamp@localhost ~]$ whoami
    2. lamp
    3. #查询用户身份,我是lamp
    4. [lamp@localhost ~]$ su root
    5. 密码:
    6. <-输入root密码
    7. #切换到root,但是没有切换环境变量。注意:普通用户切换到root需要密码
    8. [root@localhost ~]# env | grep lamp
    9. #查看环境变量,提取包含lamp的行
    10. USER=lamp
    11. #用户名还是lamp,而不是root
    12. PATH=/usr/lib/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/lamp/bin
    13. #命令査找的路径不包含超级用户路径
    14. MAIL=/var/spool/mail/lamp
    15. PWD=/home/lamp
    16. LOGNAME=lamp
    17. #邮箱、主目录、目前用户名还是lamp
    可以看到,在不使用 su - 的情况下,虽然用户身份成功切换,但环境变量依旧用的是原用户的,切换并不完整。
    1. LOGNAME=lamp
    2. #邮箱、主目录、目前用户名还是lamp
    可以看到,在不使用 su - 的情况下,虽然用户身份成功切换,但环境变量依旧用的是原用户的,切换并不完整。

1.10 groupadd 命令:添加用户组

groupadd 命令用于创建一个新的工作组,新工作组的信息将被添加到系统文件中。
相关文件:

  • /etc/group 组账户信息。
  • /etc/gshadow 安全组账户信息。
  • /etc/login.defs Shadow密码套件配置。

    1.10.1 语法格式

    groupadd 命令 语法格式如下:
    **_[root@localhost ~]# groupadd [选项] 组名_**
    选项

  • -g:指定新建工作组的 id;

  • -r:创建系统工作组,系统工作组的组 ID 小于 500;
  • -K:覆盖配置文件 /etc/login.defs;
  • -o:允许添加组 ID 号不唯一的工作组。
  • -f,—force: 如果指定的组已经存在,此选项将失明了仅以成功状态退出。当与 -g 一起使用,并且指定的 GID_MIN 已经存在时,选择另一个唯一的 GID(即 -g 关闭)。

    1.10.2 例子

    例 1

    使用 groupadd 命令创建新群组非常简单,例如:

    1. [root@localhost ~]# groupadd group1
    2. #添加group1组
    3. [root@localhost ~]# grep "group1" /etc/group
    4. /etc/group:group1:x:502:
    5. /etc/gshadow:group1:!::

    1.11 groupmod 命令:修改用户组

    Linux groupmod命令用于更改群组识别码或名称。
    需要更改群组的识别码或名称时,可用 groupmod 指令来完成这项工作。

    1.11.1 语法格式

    groupadd 命令 语法格式如下:
    **_[root@localhost ~]# groupmod [选项] 组名_**
    选项

  • -g <群组识别码>:设置欲使用的群组识别码。

  • -o:重复使用群组识别码。
  • -n <新群组名称>:设置欲使用的群组名称。

    1.11.2 例子

    例 1

    1. [root@localhost ~]# groupmod -n testgrp group1
    2. #把组名group1修改为testgrp
    3. [root@localhost ~]# grep "testgrp" /etc/group
    4. testgrp:x:502:
    5. #注意GID还是502,但是组名已经改变
    大家还是要注意,用户名不要随意修改,组名和 GID 也不要随意修改,因为非常容易导致管理员逻辑混乱。如果非要修改用户名或组名,则建议大家先删除旧的,再建立新的。

1.12 groupdel 命令:刪除用户组

Linux groupdel 命令用于删除群组。
需要从系统上删除群组时,可用 groupdel (group delete) 指令来完成这项工作。倘若该群组中仍包括某些用户,则必须先删除这些用户后,方能删除群组。

1.12.1 语法格式

groupdel 命令基本格式为:
**_[root__@localhost__ ~]__#groupdel 组名_**
通过前面的学习不难猜测出,使用 groupdel 命令删除群组,其实就是删除 /etc/group 文件和 /etc/gshadow 文件中有关目标群组的数据信息。

1.12.2 例子

例 1

删除前面章节中用 groupadd 命令创建的群组 group1,执行命令如下:

  1. [root@localhost ~]#grep "group1" /etc/group /etc/gshadow
  2. /etc/group:group1:x:505:
  3. /etc/gshadow:group1:!::
  4. [root@localhost ~]#groupdel group1
  5. [root@localhost ~]#grep "group1" /etc/group /etc/gshadow
  6. [root@localhost ~]#

例 2

不能使用 groupdel 命令随意删除群组。此命令仅适用于删除那些 “不是任何用户初始组” 的群组,换句话说,如果有群组还是某用户的初始群组,则无法使用 groupdel 命令成功删除。例如:

  1. [root@localhost ~]# useradd temp
  2. #运行如下命令,可以看到 temp 用户建立的同时,还创建了 temp 群组,且将其作为 temp用户的初始组(组ID都是 505)
  3. [root@localhost ~]# grep "temp" /etc/passwd /etc/group /etc/gshadow
  4. /etc/passwd:temp:x:505:505::/home/temp:/bin/bash
  5. /etc/group:temp:x:505:
  6. /etc/gshadow:temp:!::
  7. #下面尝试删除 temp 群组
  8. [root@localhost ~]# groupdel temp
  9. groupdel:cannot remove the primary group of user 'temp'

可以看到,groupdel 命令删除 temp 群组失败,且提示“不能删除 temp 用户的初始组”。如果一定要删除 temp 群组,要么修改 temp 用户的 GID,也就是将其初始组改为其他群组,要么先删除 temp 用户。
切记,虽然我们已经学了如何手动删除群组数据,但胡乱地删除群组可能会给其他用户造成不小的麻烦,因此更改文件数据要格外慎重。

1.13 gpasswd 命令:把用户添加进组或从组中删除

为了避免系统管理员(root)太忙碌,无法及时管理群组,我们可以使用 gpasswd 命令给群组设置一个群组管理员,代替 root 完成将用户加入或移出群组的操作。

1.13.1 语法格式

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 gpasswd 命令各选项及其功能
从表 1 可以看到,除 root 可以管理群组外,可设置多个普通用户作为群组的管理员,但也只能做“将用户加入群组”和“将用户移出群组”的操作。

1.13.2 例子

例 1

  1. #创建新群组 group1,并将群组交给 lamp 管理
  2. [root@localhost ~]# groupadd group1 <-- 创建群组
  3. [root@localhost ~]# gpasswd group1 <-- 设置密码吧!
  4. Changing the password for group group1
  5. New Password:
  6. Re-enter new password:
  7. [root@localhost ~]# gpasswd -A lamp group1 <==加入群组管理员为 lamp
  8. [root@localhost ~]# grep "group1" /etc/group /etc/gshadow
  9. /etc/group:group1:x:506:
  10. /etc/gshadow:group1:$1$I5ukIY1.$o5fmW.cOsc8.K.FHAFLWg0:lamp:

可以看到,此时 lamp 用户即为 group1 群组的管理员。

例 2

  1. #以lamp用户登陆系统,并将用户 lamp 和 lamp1 加入group1群组。
  2. [lamp@localhost ~]#gpasswd -a lamp group1
  3. [lamp@localhost ~]#gpasswd -a lamp1 group1
  4. [lamp@localhost ~]#grep "group1" /etc/group
  5. group1:x:506:lamp,lamp1

前面讲过,使用 usermod -G 命令也可以将用户加入群组,但会产生一个问题,即使用此命令将用户加入到新的群组后,该用户之前加入的那些群组都将被清空。例如:

  1. #新创建一个群组group2
  2. [root@localhost ~]# groupadd group2
  3. [root@localhost ~]# usermod -G group2 lamp
  4. [root@localhost ~]# grep "group2" /etc/group
  5. group2:x:509:lamp
  6. [root@localhost ~]# grep "group1" /etc/group
  7. group1:x:506:lamp1

对比例 2 可以发现,虽然使用 usermod 命令成功地将 lamp 用户加入在 group2 群组中,但 lamp 用户原本在 group1 群组中,此时却被移出,这就是使用 usermod 命令造成的。
因此,将用户加入或移出群组,最好使用 gpasswd 命令。

1.14 newgrp 命令:切换用户的有效组

我们知道,每个用户可以属于一个初始组(用户是这个组的初始用户),也可以属于多个附加组(用户是这个组的附加用户)。既然用户可以属于这么多用户组,那么用户在创建文件后,默认生效的组身份是哪个呢?
当然是初始用户组的组身份生效,因为初始组是用户一旦登陆就获得的组身份。也就是说,用户的有效组默认是初始组,因此所创建文件的属组是用户的初始组。那么,既然用户属于多个用户组,能不能改变用户的初始组呢?使用命令 newgrp 就可以。
newgrp 命令可以从用户的附加组中选择一个群组,作为用户新的初始组。

1.14.1 语法格式

newgrp 命令的基本格式如下:
**_[root__@localhost__ ~]__# newgrp 组名_**

1.14.2 样例

  1. 首先,建立 3 个用户组 group1、group2 和 group3,命令如下:

    1. [root@localhost ~]# groupadd group1
    2. [root@localhost ~]# groupadd group2
    3. [root@localhost ~]# groupadd group3
  2. 创建一个用户 user1,同时指定 user1 的初始组为 group1,附加组为 group2 和 group3,执行命令如下:

    1. [root@localhost ~]# useradd -g group1 -G group2,group3 user1
    2. #由于指定了初始组,因此不会在创建 user1 默认群组
    3. [root@localhost ~]# more /etc/group | grep user1
    4. group2:x:501:user1
    5. group3:x:502:user1
  3. 对用户 user1 设置密码,执行命令如下:

    1. [root@localhost ~]# passwd user1
    2. Changing password for user user1.
    3. New password:
    4. Retype new password:
    5. passwd: all authentication tokens updated successfully.
  4. 切换至 user1 用户,通过 newgrp 切换用户组进行下列操作,读者可从中体会出 newgrp 命令的作用。

    1. #切换至 user1 用户
    2. [root@localhost ~]# su - user1
    3. [root@localhost ~]# whoami
    4. user1
    5. #使用 newgrp 命令一边切换 user1 的初始组,一边创建文件
    6. [root@localhost ~]# mkdir user1_doc
    7. [root@localhost ~]# newgrp group2
    8. [root@localhost ~]# mkdir user2_doc
    9. [root@localhost ~]# newgrp group3
    10. [root@localhost ~]# mkdir user3_doc
    11. #查看各文件的详细信息
    12. [root@localhost ~]# ll
    13. total 12
    14. drwxr-xr-x 2 user1 group1 4096 Oct 24 01:18 user1_doc
    15. drwxr-xr-x 2 user1 group2 4096 Oct 24 01:18 user2_doc
    16. drwxr-xr-x 2 user1 group3 4096 Oct 24 01:19 user3_doc

    可以看到,通过使用 newgrp 命令切换用户的初始组,所创建的文件各自属于不同的群组,这就是 newgrp 所发挥的作用,即通过切换附加组成为新的初始组,从而让用户获得使用各个附加组的权限。