- 第14章 Linux账号管理与ACL权限设置
- 1. 先查看一下,系统里面有没有一个名为 dmtsai 的用户
- 瞧一瞧!用户的字段正是 dmtsai 本身。
- 2. 修改一下,将刚才我们的 dmtsai 的 503 UID 改为 2000 看看:
- 怎么变成 503 了?因为文件只会记录数字而已。
- 因为我们乱改,所以导致 503 找不到对应的账号,因此显示数字!
- 3. 记得将刚才的 2000 改回来!
- 14.2 账号管理
- 默认会创建用户主文件夹,且权限为 700 !这是重点!
- 看一下,UID 与 initial group 确实改变成我们需要的了!
- 上面说明密码新建时间 (2009-02-26)、最小天数(0)、更改天数(99999)、警告天数(7)
- 与密码不会失效 (-1) 。
- 状态变成“ LK, Lock ”,就无法登录了。
- 其实只是在这里加上 !! 而已!
- 密码字段恢复正常!
- 此时此账号的密码新建时间会被改为 1970/1/1 ,所以会有问题!
- 使用 chown -R 是为了连同主文件夹下面的用户/组属性都一起更改
- 使用 chmod 没有 -R , 是因为我们仅要修改目录的权限而非内部文件的权限!
- 其实就是改到第五个字段,该字段里面用多个“ , ”分隔就是了!
- 就是上面特殊字体呈现的那些地方是由 chfn 所修改出来的!
- 其实上面的信息就是我们在 bash 中谈到的 /etc/shells
- 测试完毕后,立刻改回来!
- 上面信息其实是同一行的数据!包括会显示 UID/GID 以及支持的所有用户组!
- 至于后面那个 context=… 则是 SELinux 的内容,先不要理会它!
- 用户组的 GID 也是会由 500 以上最大 GID+1 来决定!
- 关于系统管理员(root)做的动作:
- 关于用户组管理员(Group administrator)做的操作:
- 输入两次密码就对了!
- 很有趣吧!此时 vbird1 则拥有 testgroup 的主控权,身份有点像版主。
- 看得出来,vbird1 尚未加入 testgroup 用户组。
- 先处理账号相关属性的数据:
- 再处理账号的密码相关属性的数据:
- 1. 假设这三个账号都尚未新建,可先新建一个名为 projecta 的用户组,
- 再让这三个用户加入其次要用户组的支持即可:
- 2. 开始新建此项目的开发目录:
- 其他选项鸟哥都将它省略了。假设我们只要看这两个设备,但没有看到 acl 。
- 这样就加入了!但是如果想要每次开机都生效,那就这样做:
- 1. 针对特定用户的方式:
- 设置规定:“ u:[用户账号列表]:[rwx] ”,例如针对 vbird1 的权限规定 rx :
- 权限部分多了个 + ,且与原本的权限 (644) 看起来区别很大!但要如何查阅呢?
- 无用户列表,代表设置该文件所有者,所以上面显示 root 的权限成为 rwx 了!
- 请列出刚才我们设置的 acl_test1 的权限内容:
- file: acl_test1 <==说明文件名而已。
- owner: root <==说明此文件的所有者,即 ll 看到的第三用户字段
- group: root <==此文件的所属用户组,亦即 ll 看到的第四用户组字段
- 2. 针对特定用户组的方式:
- 设置规范:“ g:[用户组列表]:[rwx] ”,例如针对 mygroup1 的权限规范 rx :
- file: acl_test1
- owner: root
- group: root
- 3. 针对有效权限 mask 的设置方式:
- 设置规定:“ m:[rwx] ”,例如针对刚才的文件规定为仅有 r :
- file: acl_test1
- owner: root
- group: root
- 1. 先测试看看使用 myuser1 能否进入该目录
- 2. 开始用 root 的身份来设置一下该目录的权限吧!
- file: srv/projecta
- owner: root
- group: projecta
- 3. 还是得要使用 myuser1 去测试看看结果!
- 4. 针对默认权限的设置方式:
- 设置规范:“ d:[ug]:用户列表:[rwx] ”
- 让 myuser1 在 /srv/projecta 下面一直具有 rx 的默认权限!
- file: srv/projecta
- owner: root
- group: projecta
- 确实有继承。然后我们使用 getfacl 再次确认。
- file: zzz2
- owner: root
- group: projecta
- 虽然你的 UID 已经是具有 root 的身份,但是看到上面的输出信息吗?
- 还是有一堆变量为原本 vbird1 的身份,所以很多数据还是无法直接利用。
- 了解区别了吧?下次切换成为 root 时,记得最好使用 su – 。
- 特别留意,这个文件的权限是由 sshd 所新建的。
- 要注意,新建者的身份是 vbird1 ,且我们使用 sh -c "一串命令" 来执行。
- 因为不是 root 嘛!所以当然不能查询 /etc/shadow
- 1) Respect the privacy of others. <==这里仅是一些说明与警示选项
- 2) Think before you type.
- 3) With great power comes great responsibility.
- 看!vbird1 竟然可以查询 shadow !
- 在最左边加上 % ,代表后面接的是一个“用户组”之意!改完请保存后离开
- 仔细看错误信息它是说这个 pro2 不在 /etc/sudoers 的设置中!
- 在最左边加上 % ,代表后面接的是一个“用户组”之意!改完请保存后离开
- %PAM-1.0 <==PAM版本的说明而已!
- %PAM-1.0
- pam_selinux.so close should be the first session rule
- pam_selinux.so open should only be followed by sessions…
- 我们可以看到,其实 login 也调用多次的 system-auth ,所以下面列出该配置文件
- %PAM-1.0
- This file is auto-generated.
- User changes will be destroyed the next time authconfig is run.
- 账号 限制依据限制项目 限制值
- 第一字段为账号,或者是用户组!若为用户组则前面需要加上 @ ,例如 @projecta
- 第二字段为限制的依据,是严格(hard)或者警告(soft)
- 第三字段为相关限制,此例中限制文件容量
- 第四字段为限制的值,在此例中单位为 KB
- 若以 vbird1 登录后,进行如下的操作则会有相关的限制出现!
- 果然有限制到了
- 如果要使用用户组功能的话,这个功能似乎对初始用户组才有效。
- 而如果你尝试多个 pro1 的登录时,第二个以后就无法登录了。
- 而且在 /var/log/secure 文件中还会出现如下的信息:
- pam_limits(login:session): Too many logins (max 1) for pro1
- 第一行显示目前的时间、开机 (up) 多久,几个用户在系统上的平均负载等;
- 第二行只是各个项目的说明;
- 第三行以后,每行代表一个用户。如上所示,root 登录并取得终端机名 pts/1 之意。
- 结束时,请按下 [crtl]-d 来结束输入。此时在 vbird1 的界面中会出现:
- 14.7 手动新增用户
- 在最后一行加入下面这一行!
- 最后确定 /etc/group、/etc/gshadow 都存在这个用户组才行
- 在最后一行加入下面这一行!
- 确定 /etc/passwd、/etc/shadow 都含有 normaluser 的信息了!但是密码还不对~
- !/bin/bash
- 这个程序用来新建账号,功能有:
- 1. 检查 account1.txt 是否存在,并将该文件内的账号取出;
- 2. 新建上述文件的账号;
- 3. 将上述账号的密码修改成为强制第一次进入需要修改密码的格式。
- 2009/03/04 VBird
- 检查 account1.txt 是否存在
- !/bin/bash
- 这个程序主要帮你新建大量的账号之用,更多的使用方法请参考:
- http://linux.vbird.org/linux_basic/0410accountmanager.php#manual_amount
- 本程序为鸟哥自行开发,在 CentOS 5.x 上使用没有问题,
- 但不保证绝不会发生错误!使用时,请自行负担风险~
- History:
- 2005/09/05 VBird 刚才才写完,使用看看先~
- 2009/03/04 VBird 加入一些语系的修改与说明,修改密码产生方式 (用 openssl)
- 1. 进行账号相关的输入先!
- 判断数字系统
- 2. 开始输出账号与密码文件!
- 3. 开始新建账号与密码!
- !/bin/bash
- !/bin/bash
- !/bin/bash
第14章 Linux账号管理与ACL权限设置
要登录Linux系统一定要有账号与密码才行,否则怎么登录?你说是吧?不过,不同的用户应该要拥有不同的权限才行。我们还可以通过 user/group 的特殊权限设置,来规定不同的用户组开发项目。在Linux的环境下,我们可以通过很多方式来限制用户能够使用的系统资源,包括第11章bash提到的ulimit限制,还有特殊权限限制,如umask等。通过这些举动,我们可以规定不同用户的使用资源。另外,还记得系统管理员的账号吗?对!就是root。请问一下,除了 root 之外,是否可以有其他的系统管理员账号?为什么大家都要尽量避免使用数字类型的账号?如何修改用户相关的信息呢?这些我们都需要了解。
14.1 Linux 的账号与用户组
管理员的工作中,相当重要的一环就是“管理账号”。因为整个系统都是你在管理的,并且所有一般用户的账号申请都必须要通过你的协助才行!所以你就必须要了解一下如何管理好一个服务器主机的账号。在管理Linux主机的账号时,我们必须先来了解一下Linux到底是如何辨别每一个用户的!
14.1.1 用户标识符:UID 与GID
虽然我们登录Linux主机的时候,输入的是我们的账号,但是其实Linux主机并不会直接认识你的“账号名称”的,它仅认识ID(ID就是一组号码)。由于计算机仅认识0与1,所以主机对于数字比较有概念的;至于账号只是为了让人们容易记忆而已。而你的ID与账号的对应关系就在/etc/passwd当中。
如果您曾经在网络上下载过 tarball 类型的文件,那么应该不难发现,在解压缩之后的文件中,文件所有者字段竟然显示“不明的数字”,因为 Linux 说实在话,它真的只认识代表您身份的号码而已!
那么到底有几种ID呢?还记得我们在第6章内有提到过,每一个文件都具有“所有者与所属用户组”的属性吗?没错啦!每个登录的用户至少都会取得两个ID,一个是用户ID(UserID,简称UID),一个是用户组 ID(Group ID,简称 GID)。
那么文件如何判别它的所有者与用户组呢?其实就是利用UID与GID。每一个文件都会有所谓的所有者ID与用户组ID,当我们有要显示文件属性的需求时,系统会依据/etc/passwd与/etc/group的内容,找到 UID/GID 对应的账号与组名再显示出来。我们可以做个小实验,你可以用 root 的身份vi/etc/passwd,然后将你的一般身份的用户的 ID 随便改一个号码,然后再到你的一般身份的目录下看看原先该账号拥有的文件,你会发现该文件的所有者变成数字了。这样可以理解了吗?来看看下面的例子:
1. 先查看一下,系统里面有没有一个名为 dmtsai 的用户
[root@www ~]# grep 'dmtsai' /etc/passwd
dmtsai:x:503:504::/home/dmtsai:/bin/bash <==是有这个账号。
[root@www ~]# ll -d /home/dmtsai
drwx——— 4 dmtsai dmtsai 4096 Feb 6 18:25 /home/dmtsai
瞧一瞧!用户的字段正是 dmtsai 本身。
2. 修改一下,将刚才我们的 dmtsai 的 503 UID 改为 2000 看看:
[root@www ~]# vi /etc/passwd
…(前面省略)…
dmtsai:x:2000:504::/home/dmtsai:/bin/bash <==修改一下特殊字体部分,由 503 改过来
[root@www ~]# ll -d /home/dmtsai
drwx——— 4 503 dmtsai 4096 Feb 6 18:25 /home/dmtsai
怎么变成 503 了?因为文件只会记录数字而已。
因为我们乱改,所以导致 503 找不到对应的账号,因此显示数字!
3. 记得将刚才的 2000 改回来!
[root@www ~]# vi /etc/passwd
….(前面省略)….
dmtsai:x:503:504::/home/dmtsai:/bin/bash <==赶紧改回来!
你一定要了解的是,上面的例子仅是在说明UID与账号的对应性,在一台正常运行的Linux主机环境下,上面的操作不可随便进行,这是因为系统上已经有很多的数据被创建了,随意修改系统上某些账号的UID很可能会导致某些程序无法进行,这将导致系统无法顺利运行的结果,因为权限的问题。所以,了解了之后,请赶快回到/etc/passwd里面将数字改回来。
举例来说,如果上面的测试最后一个步骤没有将2000改回原本的UID,那么当dmtsai下次登录时将没有办法进入自己的主文件夹。因为它的UID已经改为2000,但是它的主文件夹(/home/dmtsai)却记录的是503,由于权限是700,因此它将无法进入原本的主文件夹!是否非常严重啊?
14.1.2 用户账号
Linux系统上面的用户如果需要登录主机以取得shell的环境来工作时,它需要如何进行呢?首先,它必须要在计算机前面利用tty1~tty7的终端机提供的login接口,并输入账号与密码后才能够登录。如果是通过网络的话,那至少用户就得要学习 ssh 这个功能了(服务器篇再来谈)。那么你输入账号密码后,系统帮你处理了什么呢?
1.先找寻/etc/passwd 里面是否有你输入的账号,如果没有则跳出,如果有的话则将该账号对应的UID与GID(在/etc/group中)读出来,另外,该账号的主文件夹与shell设置也一并读出。
2.再来则是核对密码表啦!这时Linux会进入/etc/shadow里面找出对应的账号与UID,然后核对一下你刚才输入的密码与里面的密码是否相符。
3.如果一切都OK的话,就进入shell控管的阶段了。
大致上的情况就像这样,所以当你要登录你的Linux主机的时候,那个/etc/passwd与/etc/shadow就必须要让系统读取(这也是很多攻击者会将特殊账号写到/etc/passwd里面去的缘故),所以呢,如果你要备份Linux的系统的账号的话,那么这两个文件就一定需要备份才行。
由上面的流程我们也知道,跟用户账号有关的有两个非常重要的文件,一个是管理用户UID/GID重要参数的/etc/passwd,一个则是专门管理密码相关数据的/etc/shadow。那这两个文件的内容就非常值得进行研究。下面我们会简单介绍这两个文件,详细的说明可以参考 man 5 passwd 及 man 5shadow [1]。
/etc/passwd文件结构
这个文件的构造是这样的:每一行都代表一个账号,有几行就代表有几个账号在你的系统中!不过需要特别留意的是,里面很多账号本来就是系统正常运行所必须要的,我们可以简称它为系统账号,例如bin,daemon,adm,nobody等,这些账号请不要随意删掉。这个文件的内容有点像这样:
鸟哥在接触Linux之前曾经碰过Solaris系统(1999年),当时鸟哥啥也不清楚!由于“听说”Linux 上面的账号越复杂会导致系统越危险。所以鸟哥就将/etc/passwd 上面的账号全部删除到只剩下root与鸟哥自己用的一般账号。结果您猜发生什么事?那就是调用Sun的工程师来维护系统,糗到不行!
[root@www ~]# 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
我们先来看一下每个Linux系统都会有的第一行,就是root这个系统管理员那一行好了,你可以明显看出来,每一行使用“:”分隔开,共有七个字段,分别是:
1.账号名称
就是账号。用来对应UID的。例如root的UID对应就是0(第三字段)
2.密码
早期 UNIX 系统的密码就是放在这字段上!但是因为这个文件的特性是所有的程序都能够读取,这样一来很容易造成密码数据被窃取,因此后来就将这个字段的密码数据改放到/etc/shadow 中了,所以这里你会看到一个“x”。
3.UID
这个就是用户标识符。通常Linux对于UID有几个限制,需要说给你了解一下,如表14-1所示。
表14-1
上面这样说明可以了解了吗?是的,UID 为 0 的时候,就是 root。所以请特别留意一下你的/etc/passwd文件!
4.GID
这个与/etc/group 有关!其实/etc/group 与/etc/passwd 差不多,只是它是用来规定组名与 GID的对应而已!
5.用户信息说明列
这个字段基本上并没有什么重要用途,只是用来解释这个账号的意义而已。不过,如果你提供使用finger的功能时,这个字段可以提供很多的信息。本章后面的chfn命令会来解释这里的说明。
6.主文件夹
这是用户的主文件夹,以上面为例,root的主文件夹在/root中,所以当root登录之后,就会立刻跑到/root目录里面。如果你有个账号的使用空间特别大,你想要将该账号的主文件夹移动到其他的硬盘去该怎么做?可以在这个字段进行修改。默认的用户主文件夹在/home/yourIDname中。
7.Shell
我们在第11章BASH提到很多次,当用户登录系统后就会取得一个Shell来与系统的内核通信以进行用户的操作任务。那为何默认shell会使用bash呢?就是在这个字段指定的。这里比较需要注意的是,有一个shell可以用来替代成让账号无法取得shell环境的登录操作。那就是/sbin/nologin。这也可以用来制作纯pop邮件账号者的数据呢!
/etc/shadow文件结构
我们知道很多程序的运行都与权限有关,而权限与UID/GID有关!因此各程序当然需要读取/etc/passwd来了解不同账号的权限。因此/etc/passwd的权限需设置为-rw-r—r—这样的情况,虽然早期的密码也有加密过,但却放置到/etc/passwd的第二个字段上!这样一来很容易被有心人士所窃取,加密过的密码也能够通过暴力破解法去 try and error(试误)找出来!
因为这样的关系,所以后来发展出将密码移动到/etc/shadow这个文件分隔开来的技术,而且还加入很多的密码限制参数在/etc/shadow里面呢!在这里,我们先来了解一下这个文件的构造吧!鸟哥的/etc/shadow文件有点像这样:
[root@www ~]# head -n 4 /etc/shadow
root:$1$/30QpE5e$y9N/D0bh6rAACBEz.hqo00:14126:0:99999:7::: <==下面说明用
bin:*:14126:0:99999:7:::
daemon:*:14126:0:99999:7:::
adm:*:14126:0:99999:7:::
基本上,shadow同样以“:”作为分隔符,如果数一数,会发现共有9个字段啊,这9个字段的用途是这样的。
1.账号名称
由于密码也需要与账号对应。因此,这个文件的第一列就是账号,必须要与/etc/passwd相同才行!
2.密码
这个字段内的数据才是真正的密码,而且是经过编码的密码(加密)。你只会看到有一些特殊符号的字母就是了!需要特别留意的是,虽然这些加密过的密码很难被解出来,但是“很难”不等于“不可能”,所以,这个文件的默认权限是“-rw———-”或者是“-r————”,即只有 root 才可以读写就是了!你得随时注意,不要不小心改动了这个文件的权限呢!
另外,由于各种密码编码的技术不一样,因此不同的编码系统会造成这个字段的长度不相同。举例来说,旧式的DES编码系统产生的密码长度就与目前惯用的MD5不同 [2]!MD5的密码长度明显比较长些。由于固定的编码系统产生的密码长度必须一致,因此当你让这个字段的长度改变后,该密码就会失效(算不出来)。很多软件通过这个功能,在此字段前加上!或*改变密码字段长度,就会让密码“暂时失效”了。
3.最近更动密码的日期
这个字段记录了改动密码的日期,不过,在我的例子中怎么会是14126呢?这个是因为计算Linux日期的时间是以1970年1月1日作为1而累加的日期,1971年1月1日则为366啦!得注意一下这个数据。上述的14126指的就是2008-09-04那一天啦!而想要了解该日期可以使用本章后面chage命令的帮忙!至于想要知道某个日期的累积日数,可使用如下的程序计算:
[root@www ~]# echo $(($(date —date="2008/09/04" +%s)/86400+1))
14126
上述命令中,2008/09/04为你想要计算的日期,86400为每一天的秒数,%s为1970/01/01以来的累积总秒数。由于bash仅支持整数,因此最终需要加上1补齐1970/01/01当天。
4.密码不可被更动的天数(与第3个字段相比)
第4个字段记录了这个账号的密码在最近一次被更改后需要经过几天才可以再被更改!如果是0的话,表示密码随时可以改动的意思。这的限制是为了怕密码被某些人一改再改而设计的!如果设置为20天的话,那么当你设置了密码之后,20天之内都无法改变这个密码。
5.密码需要重新更改的天数(与第3个字段相比)
经常更改密码是个好习惯。为了强制要求用户更改密码,这个字段可以指定在最近一次更改密码后在多少天数内需要再次的更改密码才行。你必须要在这个天数内重新设置你的密码,否则这个账号的密码将会变为过期特性。而如果像上面的99999(计算为273年)的话,那就表示密码的更改没有强制性之意。
6.密码需要更改期限前的警告天数(与第5个字段相比)
当账号的密码有效期限快要到的时候(第 5 个字段),系统会依据这个字段的设置发出“警告”给这个账号,提醒他再过n天你的密码就要过期了,请尽快重新设置你的密码!”,如上面的例子,则是密码到期之前的7天之内,系统会警告该用户。
7.密码过期后的账号宽限时间(密码失效日)(与第5个字段相比)
密码有效日期为“更新日期”(第3个字段)+“重新更改日期”(第5个字段),过了该期限后用户依旧没有更新密码,那该密码就算过期了。虽然密码过期但是该账号还是可以用来进行其他工作的,包括登录系统取得bash。不过如果密码过期了,那当你登录系统时,系统会强制要求你必须要重新设置密码才能登录继续使用,这就是密码过期特性。
那这个字段的功能是什么呢?是在密码过期几天后,如果用户还是没有登录更改密码,那么这个账号的密码将会“失效”,即该账号再也无法使用该密码登录了。要注意密码过期与密码失效并不相同。
8.账号失效日期
这个日期跟第三个字段一样,都是使用 1970 年以来的总日数设置。这个字段表示:这个账号在此字段规定的日期之后,将无法再使用。就是所谓的“账号失效”,此时不论你的密码是否有过期,这个“账号”都不能再被使用。这个字段会被使用通常应该是在“收费服务”的系统中,你可以规定一个日期让该账号不能再使用啦!
9.保留
最后一个字段是保留的,看以后有没有新功能加入。
举个例子来说好了,假如我的dmtsai这个用户的密码如下所示:
dmtsai:$1$vyUuj.eX$omt6lKJvMcIZHx4H7RI1V.:14299:5:60:7:5:14419:
这表示什么呢?先要注意的是14299是2009/02/24。所以dmtsai这个用户的密码相关意义是:
由于密码几乎仅能单向运算(由明码计算成为密码,无法由密码反推回明码),因此由上面的数据我们无法得知dmstai的实际密码明文;
此账号最近一次改动密码的日期是2009/02/24(14299);
能够再次修改密码的时间是5天以后,也就是2009/03/01以前dmtsai不能修改自己的密码;如果用户还是尝试要更动自己的密码,系统就会出现这样的信息:
You must wait longer to change your password
passwd: Authentication token manipulation error
界面中告诉我们:你必须要等待更久的时间才能够更改密码。
由于密码过期日期定义为60天后,即累积日数为:14299+60=14359,经过计算得到此日数代表日期为2009/04/25。这表示用户必须要在2009/03/01到2009/04/25之间的60天限制内去修改自己的密码,若2009/04/25之后还是没有更改密码时,该密码就宣告为过期了!
警告日期设为7天,即是密码过期日前的7天,在本例中则代表2009/04/19~2009/04/25这7天。如果用户一直没有更改密码,那么在这7天中,只要dmtsai登录系统就会发现如下的信息:
Warning: your password will expire in 5 days
如果该账号一直到2009/04/25都没有更改密码,那么密码就过期了。但是由于有5天的宽限天数,因此dmtsai在2009/04/30前都还可以使用旧密码登录主机,不过登录时会出现强制更改密码的情况,界面有点像下面这样:
You are required to change your password immediately (password aged)
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for user dmtsai.
Changing password for dmtsai
(current) UNIX password:
你必须要输入一次旧密码以及两次新密码后,才能够开始使用系统的各项资源。如果你是在2009/04/30以后尝试以dmtsai登录的话,那么就会出现如下的错误信息且无法登录,因为此时你的密码就失效了!
Your account has expired; please contact your system administrator
如果用户在2009/04/25以前更改过密码,那么第3个字段的那个14299的天数就会跟着改变,因此,所有的限制日期也会跟着相对变动。
无论用户如何操作,到了14419(大约是2009/07/24左右)该账号就失效了。
通过这样的说明,你应该会比较容易理解了吧?由于 shadow 有这样的重要性,因此可不能随意修改。但在某些情况下面你得要使用各种方法来处理这个文件的!举例来说,经常听到人家说“我的密码忘记了”,或者是“我的密码不知道得被谁改过,跟原先的不一样了”,这个时候怎么办?
一般用户的密码忘记了:这个最容易解决,请系统管理员帮忙,他会重新设置好你的密码而不需要知道你的旧密码!利用root的身份使用passwd命令来处理即可。
root密码忘记了:这就麻烦了!因为你无法使用root的身份登录了。但我们知道root的密码在/etc/shadow当中,因此你可以使用各种可行的方法开机进入Linux再去修改。例如重新启动进入用户维护模式(第20章)后,系统会主动给予root权限的bash接口,此时再以passwd修改密码即可;或以 Live CD 开机后挂载根目录去修改/etc/shadow,将里面的 root 的密码字段清空,再重新启动后root将不用密码即可登录!登录后再赶快以passwd命令去设置root密码即可。
曾经听过一则笑话,某位老师主要是在教授Linux操作系统,但是他是新来的,因此对于该系的计算机环境不熟。由于当初安装该计算机教室Linux操作系统的人员已经离职且找不到联络方式了,也就是说root密码已经没有人清楚了。此时该老师就对学生说:“在Linux里面root密码不见了,我们只能重新安装”,感觉有点无力,又是个被Windows制约的人才!
14.1.3 有效与初始用户组:groups, newgrp
认识了账号相关的两个文件/etc/passwd与/etc/shadow之后,你或许还是会觉得奇怪,那么用户组的配置文件在哪里?还有,在/etc/passwd的第四列不是所谓的GID吗?那又是什么?此时就需要了解/etc/group与/etc/gshadow。
/etc/group文件结构
这个文件就是记录GID与组名的对应。鸟哥测试机的/etc/group内容有点像这样:
[root@www ~]# head -n 4 /etc/group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
这个文件每一行代表一个用户组,也是以冒号“:”作为字段的分隔符,共分为四列,每一字段的意义是:
1.用户组名称
就是用户组名称啦!
2.用户组密码
通常不需要设置,这个设置通常是给“用户组管理员”使用的,目前很少有这个机会设置用户组管理员。同样,密码已经移动到/etc/gshadow去,因此这个字段只会存在一个“x”而已。
3.GID
就是用户组的ID。我们/etc/passwd第四个字段使用的GID对应的用户组名就是由这里对应出来的!
4.此用户组支持的账号名称
我们知道一个账号可以加入多个用户组,那某个账号想要加入此用户组时,将该账号填入这个字段即可。举例来说,如果我想要让 dmtsai 也加入 root 这个用户组,那么在第一行的最后面加上“,dmtsai”,注意不要有空格,使其成为“root:x:0:root,dmtsai”就可以。
谈完了/etc/passwd、/etc/shadow、/etc/group之后,我们可以使用一个简单的图示来了解一下UID/GID与密码之间的关系,如图14-1所示。其实重点是/etc/威者 passwd,其他相关的数据都是根据这个文件的字段去找寻出来的。图中root的UID是0,而GID也是0,寻找/etc/group可以知道GID为0时的组名就是root。至于密码的寻找中,会找到/etc/shadow与/etc/passwd内同账号名称的那一行,就是密码相关数据。
图14-1 账号相关文件之间的UID/GID与密码相关性示意图
至于在/etc/group比较重要的特色在于第四列,因为每个用户都可以拥有多个支持的用户组,这就好比在学校念书的时候,我们可以加入多个社团一样。不过这里你或许会觉得奇怪的,那就是假如我同时加入多个用户组,那么我在作业的时候,到底是以那个用户组为准?下面我们就来谈一谈这个“有效用户组”的概念。
有效用户组(effective group)与初始用户组(initial group)
还记得每个用户在他的/etc/passwd里面的第四列有所谓的GID吧?那个GID就是所谓的“初始用户组”(initial group)。也就是说,当用户登录系统,立刻就拥有这个用户组的相关权限的意思。举例来说,我们上面提到 dmtsai 这个用户的/etc/passwd 与/etc/group 还有/etc/gshadow相关的内容如下:
[root@www ~]# usermod -G users dmtsai <==先设置好用户组
[root@www ~]# grep dmtsai /etc/passwd /etc/group /etc/gshadow
/etc/passwd:dmtsai:x:503:504::/home/dmtsai:/bin/bash
/etc/group:users:x:100:dmtsai <==次要用户组的设置
/etc/group:dmtsai:x:504: <==因为是初始用户组,所以第四个字段不需要填入账号
/etc/gshadow:users:::dmtsai <==次要用户组的设置
/etc/gshadow:dmtsai:!::
仔细看到上面内容,在/etc/passwd里面,dmtsai这个用户所属的用户组为GID=504,寻找一下/etc/group 得到 504 是那个名为 dmtsai 的用户组。这就是 initial group。因为是初始用户组,用户一登录就会主动取得,不需要在/etc/group的第四个字段写入该账号的!
但是非 initial group 的其他用户组可就不同了。举上面这个例子来说,我将 dmtsai 加入 users这个用户组当中,由于 users 这个用户组并非是 dmtsai 的初始用户组,因此,我必须要在/etc/group这个文件中找到users那一行,并且将dmtsai这个账号加入第四列,这样dmtsai才能够加入users这个用户组。
那么在这个例子当中,因为我的dmtsai账号同时支持dmtsai与users这两个用户组,因此,在读取/写入/执行文件时,针对用户组部分,只要是 users 与 dmtsai 这两个用户组拥有的功能,dmtsai 这个用户都能够拥有。不过,这是针对已经存在的文件而言,如果今天我要新建一个新的文件或者是新的目录,请问一下,新文件的组是 dmtsai 还是 users?这就得要检查一下当时的有效用户组了(effective group)。
groups:有效与支持用户组的查看
如果我以dmtsai这个用户的身份登录后,该如何知道我所有支持的用户组呢?很简单啊,直接输入groups就可以了!注意,是groups,有加s呢!结果像这样:
[dmtsai@www ~]$ groups
dmtsai users
在这个输出的信息中,可知道dmtsai这个用户同时属于dmtsai及users这个两个组,而且,第一个输出的用户组即为有效用户组(effective group)了。也就是说,我的有效用户组为dmtsai。此时,如果我以 touch 去创建一个新文件,例如“touch test”,那么这个文件的所有者为dmtsai,而且用户组也是dmtsai的。
[dmtsai@www ~]$ touch test
[dmtsai@www ~]$ ll
-rw-rw-r— 1 dmtsai dmtsai 0 Feb 24 17:26 test
这样是否可以了解什么是有效用户组了?通常有效用户组的作用是新建文件。那么有效用户组是否能够变换?
newgrp:有效用户组的切换
那么如何更改有效用户组呢?就使用newgrp。不过使用newgrp是有限制的,那就是你想要切换的用户组必须是你已经有支持的用户组。举例来说,dmtsai可以在dmtsai/users这两个用户组间切换有效用户组,但是dmtsai无法切换有效用户组成为sshd。使用的方式如下:
[dmtsai@www ~]$ newgrp users
[dmtsai@www ~]$ groups
users dmtsai
[dmtsai@www ~]$ touch test2
[dmtsai@www ~]$ ll
-rw-rw-r— 1 dmtsai dmtsai 0 Feb 24 17:26 test
-rw-r—r— 1 dmtsai users 0 Feb 24 17:33 test2
此时,dmtsai的有效用户组就成为users了。我们额外来讨论一下newgrp这个命令,这个命令可以更改目前用户的有效用户组,而且是另外以一个 shell 来提供这个功能的,所以,以上面的例子来说,dmtsai这个用户目前是以另一个 shell 登录的,而且新的 shell 给予dmtsai 有效GID 为users就是了。如果以图示来看就是如图14-2所示。
图14-2 newgrp的运行示意图
虽然用户的环境设置(例如环境变量等其他数据)不会有影响,但是用户的“用户组权限”将会重新被计算。但是需要注意,由于是新取得一个 shell,因此如果你想要回到原本的环境中,请输入exit回到原本的shell。
既然如此,也就是说,只要我的用户有支持的用户组就是能够切换成为有效用户组。好了,那么如何让一个账号加入不同的用户组就是问题的所在。你要加入一个用户组有两个方式,一个是通过系统管理员(root)利用usermod帮你加入,如果root太忙了而且你的系统有设置用户组管理员,那么你可以通过用户组管理员以gpasswd帮你加入他所管理的用户组中!详细的做法留待下一小节再来介绍。
/etc/gshadow
刚才讲了很多关于“有效用户组”的概念,另外,也提到newgrp这个命令的用法,但是,如果/etc/gshadow 这个设置没有弄懂的话,那么 newgrp 是无法操作的。鸟哥测试机的/etc/gshadow的内容有点像这样:
[root@www ~]# head -n 4 /etc/gshadow
root:::root
bin:::root,bin,daemon
daemon:::root,bin,daemon
sys:::root,bin,adm
这个文件内同样还是使用冒号“:”来作为字段的分隔字符,而且你会发现,这个文件几乎与/etc/group一模一样。是这样没错!不过,要注意的大概就是第二个字段。第二个字段是密码列,如果密码列上面是“!”时,表示该用户组不具有用户组管理员。至于第四个字段也就是支持的账号名称。这四个字段的意义为:
1.用户组名;
2.密码列,同样,开头为!表示无合法密码,所以无用户组管理员;
3.用户组管理员的账号(相关信息在gpasswd中介绍);
4.该用户组的所属账号(与/etc/group内容相同)。
以系统管理员的角度来说,这个gshadow最大的功能就是创建组管理员啦!那么什么是用户组管理员呢?由于系统上面的账号可能会很多,但是我们 root 可能平时太忙碌,所以当有用户想要加入某些用户组时,root 或许会没有空管理。此时如果能够创建用户组管理员的话,那么该用户组管理员就能够将那个账号加入自己管理的用户组中!可以免去 root 的忙碌。不过,由于目前有类似sudo之类的工具,所以这个组管理员的功能已经很少使用了。我们会在后续的gpasswd中介绍这个用法。
14.2 账号管理
既然要管理账号,当然是由新增与删除用户开始的。下面我们就分别来谈一谈如何新增、删除与更改用户的相关信息。
14.2.1 新增与删除用户:useradd,相关配置文件,passwd,usermod,userdel
要如何在Linux的系统中新增一个用户啊?我们登录系统时会输入账号与密码,所以创建一个可用的账号同样也需要这两个数据。那账号可以使用useradd来新建用户,密码的给予则使用passwd这个命令!这两个命令执行方法如下:
useradd
[root@www ~]# useradd [-u UID] [-g 初始用户组] [-G 次要用户组] [-mM]\
> [-c 说明栏] [-d 主文件夹绝对路径] [-s shell] 用户账号名
参数:
-u :后面接的是 UID ,是一组数字。直接指定一个特定的 UID 给这个账号;
-g :后面接的那个用户组名就是我们上面提到的 initial group 。
该用户组的 GID 会被放置到 /etc/passwd 的第四个字段内。
-G :后面接的组名则是这个账号还可以加入的用户组。
这个参数会修改 /etc/group 内的相关数据。
-M :强制!不要创建用户主文件夹(系统账号默认值)!
-m :强制!要创建用户主文件夹(一般账号默认值)!
-c :这个就是 /etc/passwd 的第五列的说明内容。可以随便我们设置的。
-d :指定某个目录成为主文件夹,而不要使用默认值。务必使用绝对路径!
-r :创建一个系统的账号,这个账号的 UID 会有限制 (参考 /etc/login.defs)。
-s :后面接一个 shell ,若没有指定则默认是 /bin/bash 。
-e :后面接一个日期,格式为“YYYY-MM-DD”,此选项可写入 shadow 第八字段,
即账号失效日的设置选项。
-f :后面接 shadow 的第七字段选项,指定密码是否会失效。0为立刻失效,
-1 为永远不失效(密码只会过期而强制于登录时重新设置而已)。
范例一:完全参考默认值新建一个用户,名称为 vbird1
[root@www ~]# useradd vbird1
[root@www ~]# ll -d /home/vbird1
drwx——— 4 vbird1 vbird1 4096 Feb 25 09:38 /home/vbird1
默认会创建用户主文件夹,且权限为 700 !这是重点!
[root@www ~]# grep vbird1 /etc/passwd /etc/shadow /etc/group
/etc/passwd:vbird1:x:504:505::/home/vbird1:/bin/bash
/etc/shadow:vbird1:!!:14300:0:99999:7:::
/etc/group:vbird1:x:505: <==默认会创建一个与账号一模一样的用户组名
其实系统已经帮我们规定好非常多的默认值了,所以我们可以简单地使用“useradd 账号”来创建用户即可。CentOS这些默认值主要会帮我们处理几个项目:
在/etc/passwd里面创建一行与账号相关的数据,包括创建UID/GID/主文件夹等;
在/etc/shadow里面将此账号的密码相关参数填入,但是尚未有密码;
在/etc/group里面加入一个与账号名称一模一样的组名;
在/home下面创建一个与账号同名的目录作为用户主文件夹,且权限为700
由于在/etc/shadow 内仅会有密码参数而不会有加密过的密码数据,因此我们在创建用户账号时,还需要使用“passwd账号”来给予密码才算是完成了用户创建的流程。如果由于特殊需求而需要改变用户相关参数时,就得要通过上面的参数来进行创建了,参考下面的案例:
范例二:假设我已知道我的系统当中有个用户组名为 users ,且 UID 700 并不存在,
请用 users 为初始用户组,以及 uid 为 700 创建一个名为 vbird2 的账号
[root@www ~]# useradd -u 700 -g users vbird2
[root@www ~]# ll -d /home/vbird2
drwx——— 4 vbird2 users 4096 Feb 25 09:59 /home/vbird2
[root@www ~]# grep vbird2 /etc/passwd /etc/shadow /etc/group
/etc/passwd:vbird2:x:700:100::/home/vbird2:/bin/bash
/etc/shadow:vbird2:!!:14300:0:99999:7:::
看一下,UID 与 initial group 确实改变成我们需要的了!
在这个范例中,我们创建的是指定一个已经存在的用户组作为用户的初始用户组,因为用户组已经存在,所以在/etc/group里面就不会主动创建与账号同名的用户组了!此外,我们也指定了特殊的UID来作为用户的专属UID。了解了一般账号后,我们来瞧瞧那什么是系统账号(system account)吧!
范例三:创建一个系统账号,名称为 vbird3
[root@www ~]# useradd -r vbird3
[root@www ~]# ll -d /home/vbird3
ls: /home/vbird3: No such file or directory <==不会主动创建主文件夹
[root@www ~]# grep vbird3 /etc/passwd /etc/shadow /etc/group
/etc/passwd:vbird3:x:100:103::/home/vbird3:/bin/bash
/etc/shadow:vbird3:!!:14300::::::
/etc/group:vbird3:x:103:
我们在谈到UID的时候曾经说过一般账号应该是500号以后,那用户自己创建的系统账号则一般是由100号以后起算的。所以在这里我们加上-r这个参数以后,系统就会主动将账号与账号同名用户组的UID/GID都指定小于500以下,在本案例中则是使用100(UID)与103 (GID)。此外,由于系统账号主要是用来进行运行系统所需服务的权限设置,所以系统账号默认都不会主动创建主文件夹的!
由这几个范例我们也会知道,使用 useradd 创建用户账号时,其实会更改不少地方,至少我们就知道下面几个文件:
用户账号与密码参数方面的文件:/etc/passwd,/etc/shadow
用户组相关方面的文件:/etc/group,/etc/gshadow
用户的主文件夹:/home/账号名称
那请教一下,你有没有想过,为何“useradd vbird1”会主动在/home/vbird1 中创建起用户的主文件夹?主文件夹内有什么数据且来自哪里?为何默认使用的是/bin/bash 这个 shell?为何密码字段已经都规定好了(0:99999:7那一串)?这就得要说明一下useradd所使用的参考文件了。
useradd参考文件
其实useradd的默认值可以使用下面的方法调用出来:
[root@www ~]# useradd -D
GROUP=100 <==默认的用户组
HOME=/home <==默认的主文件夹所在目录
INACTIVE=-1 <==密码失效日,在 shadow 内的第 7 列
EXPIRE= <==账号失效日,在 shadow 内的第 8 列
SHELL=/bin/bash <==默认的 shell
SKEL=/etc/skel <==用户主文件夹的内容数据参考目录
CREATE_MAIL_SPOOL=yes <==是否主动帮用户创建邮件信箱(mailbox)
这个数据其实是由/etc/default/useradd调用出来的!你可以自行用vim去查看该文件的内容。搭配上面刚才谈过的范例一的运行结果,上面这些设置项目所造成的行为分别是:
GROUP=100:新建账号的初始用户组使用GID为100者。
系统上面GID为100者即是users这个用户组,此设置项目指的就是让新设用户账号的初始用户组为users这一个的意思。但是我们知道CentOS上面并不是这样的,在CentOS上面默认的用户组为与账号名相同的用户组。举例来说,vbird1 的初始用户组为 vbird1。怎么会这样啊?这是因为针对用户组的角度有两种不同的机制所致,这两种机制分别是:
私有用户组机制:系统会创建一个与账号一样的用户组给用户作为初始用户组。这种用户组的设置机制会比较有保密性,这是因为用户都有自己的用户组,而且主文件夹权限将会设置为700(仅有自己可进入自己的主文件夹)之故。使用这种机制将不会参考GROUP=100这个设置值。代表性的distributions有RHEL,Fedora,CentOS等。
公共用户组机制:就是以GROUP=100这个设置值作为新建账号的初始用户组,因此每个账号都属于 users 这个用户组,且默认主文件夹通常的权限会是“drwxr-xr-x…sernameusers…”,由于每个账号都属于users用户组,因此大家都可以互相分享主文件夹内的数据之故。代表性的distributions如SuSE等。
由于我们的CentOS使用私有用户组机制,因此这个设置项目是不会生效的!
HOME=/home:用户主文件夹的基准目录(basedir)
用户的主文件夹通常是与账号同名的目录,这个目录将会放在此设置值的目录后面。所以vbird1的主文件夹就会在/home/vbird1/中了!很容易理解吧!
INACTIVE=-1:密码过期后是否会失效的设置值
我们在 shadow 文件结构当中谈过,第七个字段的设置值将会影响到密码过期后在多久时间内还可使用旧密码登录。这个选项就是指定该日期。如果是 0 代表密码过期立刻失效,如果是-1则是代表密码永远不会失效,如果是数字,如30,则代表过期30天后才失效。
EXPIRE=:账号失效的日期
就是 shadow 内的第八字段,你可以直接设置账号在那个日期后就直接失效,而不理会密码的问题。通常不会设置此选项,但如果是付费的会员制系统,或许这个字段可以设置。
SHELL=/bin/bash:默认使用的shell程序文件名
系统默认的 shell 就写在这里。假如你的系统为 mail server,你希望每个账号都只能使用 Email的收发信件功能,而不许用户登录系统取得 shell,那么可以将这里设置为/sbin/nologin,如此一来,新建的用户默认就无法登录!也免去后续使用usermod进行修改的手续!
SKEL=/etc/skel:用户主文件夹参考基准目录
这个就是指定用户主文件夹的参考基准目录。举我们的范例一为例, vbird1 主文件夹/home/vbird1 内的各项数据都是由/etc/skel 所复制过去的,所以,将来如果我想要新增用户时,该用户的环境变量~/.bashrc就设置妥当的话,你可以到/etc/skel/.bashrc去编辑一下,也可以新建/etc/skel/www 这个目录,那么将来新增用户后,在他的主文件夹下就会有 www那个目录了。
CREATE_MAIL_SPOOL=yes:创建用户的mailbox
你可以使用“ll /var/spool/mail/vbird1”看一下,会发现有这个文件的存在。这就是用户的邮件信箱!
除了这些基本的账号设置值之外,UID/GID 还有密码参数又是在哪里参考的呢?那就得要看一下/etc/login.defs。这个文件的内容有点像下面这样:
MAIL_DIR /var/spool/mail <==用户默认邮件信箱放置目录
PASS_MAX_DAYS 99999 <==/etc/shadow 内的第 5 列,多久需更改密码天数
PASS_MIN_DAYS 0 <==/etc/shadow 内的第 4 列,多久不可重新设置密码天数
PASS_MIN_LEN 5 <==密码最短的字符长度,已被 pam 模块替代,失去效用!
PASS_WARN_AGE 7 <==/etc/shadow 内的第 6 列,过期前会警告的天数
UID_MIN 500 <==用户最小的 UID,意即小于 500 的 UID 为系统保留
UID_MAX 60000 <==用户能够用的最大 UID
GID_MIN 500 <==用户自定义用户组的最小 GID,小于 500 为系统保留
GID_MAX 60000 <==用户自定义用户组的最大 GID
CREATE_HOME yes <==在不加 -M 及 -m 时,是否主动创建用户主文件夹
UMASK 077 <==用户主文件夹创建的 umask ,因此权限会是 700
USERGROUPS_ENAB yes <==使用 userdel 删除时,是否会删除初始用户组
MD5_CRYPT_ENAB yes <==密码是否经过MD5的加密机制处理
这个文件规范的数据则是如下所示:
mailbox所在目录
用户的默认 mailbox 文件放置的目录在/var/spool/mail,所以 vbird1 的 mailbox 就是在/var/spool/mail/vbird1中。
shadow 密码第 4, 5, 6 字段内容
通过PASS_MAX_DAYS等设置值来指定的。所以你知道为何默认的/etc/shadow内每一行都会有“0:99999:7”的存在了吗?不过要注意的是,由于目前我们登录时改用 PAM 模块来进行密码检验,所以那个PASS_MIN_LEN是失效的!
UID/GID指定数值
虽然Linux内核支持的账号可高达232这么多个,不过一台主机要分配这么多账号在管理上也是很麻烦的。所以在这里就针对UID/GID的范围进行限定就是了。上面的UID_MIN指的就是可登录系统的一般账号的最小UID,至于UID_MAX则是最大UID之意。
要注意的是,系统给予一个账号 UID 时,它是先参考 UID_MIN 设置值取得最小数值;由/etc/passwd 查找最大的 UID 数值,将二者相比,找出最大的那个再加一就是新账号的 UID了。我们上面已经创建了 UID 为 700 的 vbird2,如果再使用“useradd vbird4”时,你猜 vbird4的UID会是多少?答案是:701。所以中间的505~699的号码就空下来。
而如果我是想要创建系统用的账号,所以使用 useradd -r sysaccount 这个-r 的参数时,就会找“比500小的最大的那个UID+1”。
用户主文件夹设置值
为何我们系统默认会帮用户创建主文件夹?就是这个“CREATE_HOME=yes”的设置值。这个设置值会让你在使用useradd时主动加入“-m”这个产生主文件夹的参数!如果不想要创建用户主文件夹,就只能强制加上“-M”的参数在useradd命令执行时。至于创建主文件夹的权限设置呢?就通过umask这个设置值。因为是077的默认设置,因此用户主文件夹默认权限才会是“drwx———”。
用户删除与密码设置值
“USERGROUPS_ENAB yes”这个设置值的功能是:如果使用userdel 去删除一个账号时,且该账号所属的初始用户组已经没有人隶属于该用户组了,那么就删除掉该用户组,举例来说,我们刚才有创建vbird4这个账号,它会主动创建vbird4这个用户组。若vbird4这个用户组并没有其他账号将它加入支持的情况下,若使用 userdel vbird4 时,该用户组也会被删除的意思。至于“MD5_CRYPT_ENAB yes”则表示使用 MD5 来加密密码明文,而不使用旧式的DES。
现在你知道啦,使用useradd这个程序在创建Linux上的账号时至少会参考:
/etc/default/useradd
/etc/login.defs
/etc/skel/*
这些文件,不过,最重要的其实是创建/etc/passwd、/etc/shadow、/etc/group、/etc/gshadow,还有用户主文件夹。所以,如果你了解整个系统运行的状态,也是可以手动直接修改这几个文件。账号创建了,接下来处理一下用户的密码吧!
passwd
刚才我们讲到了,使用useradd创建了账号之后,在默认的情况下,该账号是暂时被封锁的,也就是说,该账号是无法登录的,你可以去瞧一瞧/etc/shadow内的第二个字段就知道了。那该如何是好?怕什么?直接设置新密码就好了嘛。对吧?设置密码就使用 passwd 。
[root@www ~]# passwd [—stdin] <==所有人均可使用来改自己的密码
[root@www ~]# passwd [-l] [-u] [—stdin] [-S] \
> [-n 日数] [-x 日数] [-w 日数] [-i 日期]账号 <==root 功能
参数:
—stdin :可以通过来自前一个管道的数据,作为密码输入,对 shell script 有帮助!
-l :是 Lock 的意思,会将 /etc/shadow 第二列最前面加上 ! 使密码失效。
-u :与 -l 相对,是 Unlock 的意思!
-S :列出密码相关参数,即 shadow 文件内的大部分信息。
-n :后面接天数,shadow 的第 4 字段,多久不可修改密码天数。
-x :后面接天数,shadow 的第 5 字段,多久内必须要改动密码。
-w :后面接天数,shadow 的第 6 字段,密码过期前的警告天数。
-i :后面接“日期”,shadow 的第 7 字段,密码失效日期。
范例一:请 root 给予 vbird2 密码
[root@www ~]# passwd vbird2
Changing password for user vbird2.
New UNIX password: <==这里直接输入新的密码,屏幕不会有任何反应
BAD PASSWORD: it is WAY too short <==密码太简单或过短的错误!
Retype new UNIX password: <==再输入一次同样的密码
passwd: all authentication tokens updated successfully. <==竟然还是成功修改了!
root果然是最伟大的人物。当我们要给予用户密码时,通过root来设置即可。root可以设置各式各样的密码,系统几乎一定会接受。如同上面的范例一,明明鸟哥输入的密码太短了,但是系统依旧可接受vbird2这样的密码设置。这个是root帮忙设置的结果,那如果是用户自己要改密码呢?包括root也是这样修改的。
范例二:用 vbird2 登录后,修改 vbird2 自己的密码
[vbird2@www ~]$ passwd <==后面没有加账号,就是改自己的密码!
Changing password for user vbird2.
Changing password for vbird2
(current) UNIX password: <==这里输入“原有的旧密码”
New UNIX password: <==这里输入新密码
BAD PASSWORD: it is based on a dictionary word <==密码检验不通过,请再想个新密码
New UNIX password: <==这里再想个来输入吧
Retype new UNIX password: <==通过密码验证!所以重复这个密码的输入
passwd: all authentication tokens updated successfully. <==有无成功看关键字
passwd 的使用真的要很注意,尤其是 root 用户啊!鸟哥在课堂上每次讲到这里,说是要帮自己的一般账号新建密码时,有一小部分的学生就是会忘记加上账号,结果就变成改变 root自己的密码,最后 root 密码就这样不见了!唉~要帮一般账号新建密码需要使用“passwd账号”的格式,使用“passwd”表示修改自己的密码。
与root不同的是,一般账号在更改密码时需要先输入自己的旧密码(即current那一行),然后再输入新密码(New那一行)。要注意的是,密码的规定是非常严格的,尤其新的distributions大多使用PAM模块来进行密码的检验,包括太短、密码与账号相同、密码为常见字符串等,都会被PAM模块检查出来而拒绝修改密码,此时会再重复出现“New”这个关键字。那时请再想个新密码!若出现“Retype”才是你的密码被接受了!重复输入新密码并且看到“successfully”这个关键字时才是修改密码成功。
与一般用户不同的是,root 并不需要知道旧密码就能够帮用户或 root 自己新建新密码。 但如此一来有困扰,就是如果您的朋友老是告诉您“我的密码真难记,帮我设置简单一点的!”时,千万不要妥协啊!这是为了系统安全。
为何用户要设定?自己的密码会这么麻烦啊?这是因为密码的安全性啦!如果密码设置太简单,一些有心人士就能够很简单地猜到你的密码,如此一来人家就可能使用你的一般账号登录你的主机或使用其他主机资源,对主机的维护会造成困扰的!所以新的distributions是使用较严格的PAM模块来管理密码,这个管理的机制写在/etc/pam.d/passwd当中。而该文件与密码有关的测试模块就是使用pam_cracklib.so,这个模块会检验密码相关的信息,并且替代/etc/login.defs内的PASS_MIN_LEN的设置啦!关于PAM我们在本章后面继续介绍,这里先谈一下,理论上,你的密码最好符合如下要求:
密码不能与账号相同;
密码尽量不要选用字典里面会出现的字符串;
密码需要超过8个字符;
密码不要使用个人信息,如身份证、手机号码、其他电话号码等;
密码不要使用简单的关系式,如1+1=2,Iamvbird等;
密码尽量使用大小写字符、数字、特殊字符($,_,-等)的组合。
为了方便系统管理,新版的 passwd 还加入了很多创意参数。鸟哥个人认为最好用的大概就是这个“—stdin”了!举例来说,你想要帮vbird2更改密码成为abc543CC,可以这样执行命令呢!
范例三:使用 standard input 新建用户的密码
[root@www ~]# echo "abc543CC" | passwd —stdin vbird2
Changing password for user vbird2.
passwd: all authentication tokens updated successfully.
这个动作会直接更新用户的密码而不用再次手动输入!好处是方便处理,缺点是这个密码会保留在命令中,将来若系统被攻破,人家可以在/root/.bash_history中找到这个密码呢!所以这个操作通常仅用在 shell script 的大量新建用户账号当中!要注意的是,这个参数并不存在所有 distributions 版本中,请使用 man passwd 确认你的 distribution 是否有支持此参数。
如果你想要让vbird2的密码具有相当的规则,举例来说你要让vbird2每60天需要更改密码,密码过期后10天未使用就宣告密码失效,那该如何处理?
范例四:管理 vbird2 的密码,使其具有 60 天更改、10 天密码失效的设置
[root@www ~]# passwd -S vbird2
vbird2 PS 2009-02-26 0 99999 7 -1 (Password set, MD5 crypt.)
上面说明密码新建时间 (2009-02-26)、最小天数(0)、更改天数(99999)、警告天数(7)
与密码不会失效 (-1) 。
[root@www ~]# passwd -x 60 -i 10 vbird2
[root@www ~]# passwd -S vbird2
vbird2 PS 2009-02-26 0 60 7 10 (Password set, MD5 crypt.)
那如果我想要让某个账号暂时无法使用密码登录主机呢?举例来说,vbird2 这家伙最近老是在主机上乱来,所以我想要暂时让他无法登录的话,最简单的方法就是让他的密码变成不合法(改变shadow的第2字段长度),处理的方法就更简单了。
范例五:让 vbird2 的账号失效,查看完毕后再让他失效
[root@www ~]# passwd -l vbird2
[root@www ~]# passwd -S vbird2
vbird2 LK 2009-02-26 0 60 7 10 (Password locked.)
状态变成“ LK, Lock ”,就无法登录了。
[root@www ~]# grep vbird2 /etc/shadow
vbird2:!!$1$50MnwNFq$oChX.0TPanCq7ecE4HYEi.:14301:0:60:7:10::
其实只是在这里加上 !! 而已!
[root@www ~]# passwd -u vbird2
[root@www ~]# grep vbird2 /etc/shadow
vbird2:$1$50MnwNFq$oChX.0TPanCq7ecE4HYEi.:14301:0:60:7:10::
密码字段恢复正常!
是否很有趣啊?你可以自行管理一下你的账号的密码相关参数。接下来让我们用更简单的方法来查阅密码参数。
chage
除了使用 passwd -S 之外,有没有更详细的密码参数显示功能呢?有的!那就是 chage 了!它的用法如下:
[root@www ~]# chage [-ldEImMW] 账号名
参数:
-l :列出该账号的详细密码参数。
-d :后面接日期,修改 shadow的第三字段(最近一次更改密码的日期),格式 YYYY-MM-DD。
-E :后面接日期,修改 shadow的第八字段(账号失效日),格式 YYYY-MM-DD。
-I :后面接天数,修改 shadow的第七字段(密码失效日期)。
-m :后面接天数,修改 shadow的第四字段(密码最短保留天数)。
-M :后面接天数,修改 shadow的第五字段(密码多久需要进行更改)。
-W :后面接天数,修改 shadow的第六字段(密码过期前警告日期)。
范例一:列出 vbird2 的详细密码参数
[root@www ~]# chage -l vbird2
Last password change : Feb 26, 2009
Password expires : Apr 27, 2009
Password inactive : May 07, 2009
Account expires : never
Minimum number of days between password change : 0
Maximum number of days between password change : 60
Number of days of warning before password expires : 7
我们在passwd的介绍中谈到了处理vbird2这个账号的密码属性流程,使用passwd -S却无法看到很清楚的说明。如果使用 chage 那可就明白多了!如上所示,我们可以清楚地知道 vbird2的详细参数。如果想要修改其他的设置值,就自己参考上面的参数,或者自行man chage一下吧!
chage 有一个功能很不错喔!如果你想要让用户在第一次登录时强制他们一定要更改密码后才能够使用系统资源,可以利用如下的方法来处理的!
范例二:新建一个名为 agetest 的账号,该账号第一次登录后使用默认密码,
但必须要更改过密码后使用新密码才能够登录系统使用 bash 环境
[root@www ~]# useradd agetest
[root@www ~]# echo "agetest" | passwd —stdin agetest
[root@www ~]# chage -d 0 agetest
此时此账号的密码新建时间会被改为 1970/1/1 ,所以会有问题!
范例三:尝试以 agetest 登录的情况
You are required to change your password immediately (root enforced)
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for user agetest.
Changing password for agetest
(current) UNIX password: <==这个账号被强制要求必须要改密码!
非常有趣吧?你会发现 agetest 这个账号在第一次登录时可以使用与账号同名的密码登录,但登录时就会被要求立刻更改密码,更改密码完成后就会被踢出系统。再次登录时就能够使用新密码登录了!这个功能对学校老师非常有帮助!因为我们不想要知道学生的密码,那么在初次上课时就使用与学号相同的账号/密码给学生,让他们登录时自行设置他们的密码,如此一来就能够避免其他同学随意使用别人的账号,也能够保证学生知道如何更改自己的密码。
usermod
所谓“人有失手,马有乱蹄”,你说是吧?所以,当然有的时候会“不小心”在使用useradd的时候加入了错误的设置数据。或者是在使用 useradd 后,发现某些地方还可以进行详细修改。此时,当然我们可以直接到/etc/passwd或/etc/shadow去修改相对应字段的数据,不过, Linux也有提供相关的命令让大家来进行账号相关数据的微调,那就是usermod。
[root@www ~]# usermod [-cdegGlsuLU] username
参数:
-c :后面接账号的说明,即 /etc/passwd 第五列的说明,可以加入一些账号的说明。
-d :后面接账号的主文件夹,即修改 /etc/passwd 的第六列。
-e :后面接日期,格式是 YYYY-MM-DD,也就是在 /etc/shadow 内的第八个字段数据。
-f :后面接天数,为 shadow 的第七字段。
-g :后面接初始用户组,修改 /etc/passwd 的第四个字段,即是 GID 的字段!
-G :后面接次要用户组,修改这个用户能够支持的用户组,修改的是 /etc/group 。
-a :与 -G 合用可增加次要用户组的支持而非设置。
-l :后面接账号名称,即是修改账号名称,/etc/passwd 的第一列!
-s :后面接 Shell 的实际文件,例如 /bin/bash 或 /bin/csh 等。
-u :后面接 UID 数字,即 /etc/passwd 第三列的数据。
-L :暂时将用户的密码冻结,让他无法登录。其实仅改 /etc/shadow 的密码。
-U :将 /etc/shadow 密码列的 ! 去掉。
如果你仔细对比,会发现usermod的参数与useradd非常类似!这是因为usermod也是用来微调useradd增加的用户参数。不过usermod还是有新增的参数,那就是-L与-U,不过这两个参数其实与passwd的-l、-u是相同的,而且也不见得会存在于所有的distribution当中!接下来,让我们谈谈一些更改参数的实例吧!
范例一:修改用户 vbird2 的说明列,加上“VBird's test”的说明。
[root@www ~]# usermod -c "VBird's test" vbird2
[root@www ~]# grep vbird2 /etc/passwd
vbird2:x:700:100:VBird's test:/home/vbird2:/bin/bash
范例二:用户 vbird2 密码在 2009/12/31 失效。
[root@www ~]# usermod -e "2009-12-31" vbird2
[root@www ~]# grep vbird2 /etc/shadow
vbird2:$1$50MnwNFq$oChX.0TPanCq7ecE4HYEi.:14301:0:60:7:10:14609:
范例三:我们新建 vbird3 这个系统账号时并没有给予主文件夹,请新建他的主文件夹
[root@www ~]# ll -d ~vbird3
ls: /home/vbird3: No such file or directory <==确认一下,确实没有主文件夹的存在!
[root@www ~]# cp -a /etc/skel /home/vbird3
[root@www ~]# chown -R vbird3:vbird3 /home/vbird3
[root@www ~]# chmod 700 /home/vbird3
[root@www ~]# ll -a~vbird3
drwx——— 4 vbird3 vbird3 4096 Sep 4 18:15 . <==用户主文件夹权限
drwxr-xr-x 11 root root 4096 Feb 26 11:45 ..
-rw-r—r— 1 vbird3 vbird3 33 May 25 2008 .bash_logout
-rw-r—r— 1 vbird3 vbird3 176 May 25 2008 .bash_profile
-rw-r—r— 1 vbird3 vbird3 124 May 25 2008 .bashrc
drwxr-xr-x 3 vbird3 vbird3 4096 Sep 4 18:11 .kde
drwxr-xr-x 4 vbird3 vbird3 4096 Sep 4 18:15 .mozilla
使用 chown -R 是为了连同主文件夹下面的用户/组属性都一起更改
使用 chmod 没有 -R , 是因为我们仅要修改目录的权限而非内部文件的权限!
userdel
这个功能就太简单了,目的在于删除用户的相关数据,而用户的数据有:
用户账号/密码相关参数:/etc/passwd, /etc/shadow
用户组相关参数:/etc/group, /etc/gshadow
用户个人文件数据:/home/username, /var/spool/mail/username..
整个命令的语法非常简单:
[root@www ~]# userdel [-r] username
参数:
-r :连同用户的主文件夹也一起删除
范例一:删除 vbird2 ,连同主文件夹一起删除
[root@www ~]# userdel -r vbird2
这个命令执行的时候要小心了!通常我们要删除一个账号的时候,你可以手动将/etc/passwd与/etc/shadow里面的该账号取消即可!一般而言,如果该账号只是暂时不启用的话,那么将/etc/shadow里面账号失效日期(第八字段)设置为0就可以让该账号无法使用,但是所有跟该账号相关的数据都会留下来!使用userdel的时机通常是你真的确定不要让该用户在主机上面使用任何数据了!
另外,其实用户如果在系统上面操作过一阵子了,那么该用户其实在系统内可能会含有其他文件的。举例来说,他的邮件信箱(mailbox)或者是例行性工作排程(crontab,第16章)之类的文件。所以,如果想要完整地将某个账号删除,最好可以在执行 userdel-r username之前,先以“find / -user username”查出整个系统内属于 username 的文件,然后再进行删除。
14.2.2 用户功能
不论是 useradd、usermod 还是 userdel,那都是系统管理员所能够使用的命令,如果我是一般身份用户,那么我是否除了密码之外,就无法更改其他的数据呢?当然不是啦!这里我们介绍几个一般身份用户常用的账号数据更改与查询命令。
finger
finger的中文字面意义是“手指”或者是“指纹”。这个finger可以查阅很多用户相关的信息。
大部分都是/etc/passwd这个文件里面的信息。我们就先来检查检查用户信息吧!
[root@www ~]# finger [-s] username
参数:
-s :仅列出用户的账号、全名、终端机代号与登录时间等;
-m :列出与后面接的账号相同者,而不是利用部分对比(包括全名部分)。
范例一:查看 vbird1 的用户相关账号属性
[root@www ~]# finger vbird1
Login: vbird1 Name: (null)
Directory: /home/vbird1 Shell: /bin/bash
Never logged in.
No mail.
No Plan.
由于 finger 类似指纹的功能,它会将用户的相关属性列出来!如上所示,其实它列出来的几乎都是/etc/passwd文件里面的东西。列出的信息说明如下:
Login:为用户账号,即/etc/passwd内的第一字段;
Name:为全名,即/etc/passwd内的第五字段(或称为批注);
Directory:就是主文件夹了;
Shell:就是使用的Shell文件所在;
Never logged in.:finger 还会调查用户登录主机的情况;
No mail.:调查 /var/spool/mail 当中的信箱数据;
No Plan.:调查 ~vbird1/.plan 文件,并将该文件取出来说明!
不过是否能够查阅到 Mail 与 Plan 则与权限有关了!因为 Mail / Plan 都是与用户自己的权限设置有关,root当然可以查阅到用户的这些信息,但是vbird1就不见得能够查到vbird3的信息,因为/var/spool/mail/vbird3与/home/vbird3/的权限分别是660、700,那vbird1当然就无法查阅得到!这样解释可以理解吧?此外,我们可以新建自己想要执行的预定计划,当然,最多是给自己看的!可以这样做:
范例二:利用 vbird1 新建自己的计划文档
[vbird1@www ~]$ echo "I will study Linux during this year." > ~/.plan
[vbird1@www ~]$ finger vbird1
Login: vbird1 Name: (null)
Directory: /home/vbird1 Shell: /bin/bash
Never logged in.
No mail.
Plan:
I will study Linux during this year.
范例三:找出目前在系统上面登录的用户与登录时间
[vbird1@www ~]$ finger
Login Name Tty Idle Login Time Office Office Phone
root root tty1 Feb 26 09:53
vbird1 tty2 Feb 26 15:21
在范例三当中,我们发现输出的信息还会有 Office、Office Phone 等信息,那这些信息要如何记录呢?下面我们会介绍chfn这个命令。来看看如何修改用户的finger数据吧!
chfn
chfn 有点像是 change finger的意思!这命令的使用方法如下:
[root@www ~]# chfn [-foph] [账号名]
参数:
-f :后面接完整的大名;
-o :你办公室的房间号码;
-p :办公室的电话号码;
-h :家里的电话号码!
范例一:vbird1 自己更改一下自己的相关信息!
[vbird1@www ~]$ chfn
Changing finger information for vbird1.
Password: <==确认身份,所以输入自己的密码
Name []: VBird Tsai test <==输入你想要呈现的全名
Office []: Dic in Ksu. Tainan <==办公室号码
Office Phone []: 06-2727175#356 <==办公室电话
Home Phone []: 06-1234567 <==家里电话号码
Finger information changed.
[vbird1@www ~]$ grep vbird1 /etc/passwd
vbird1:x:504:505:VBird Tsai test,Dic in Ksu. Tainan,06-2727175#356,06-1234567:
/home/vbird1:/bin/bash
其实就是改到第五个字段,该字段里面用多个“ , ”分隔就是了!
[vbird1@www ~]$ finger vbird1
Login: vbird1 Name: VBird Tsai test
Directory: /home/vbird1 Shell: /bin/bash
Office: Dic in Ksu. Tainan Office Phone: 06-2727175#356
Home Phone: 06-1234567
On since Thu Feb 26 15:21 (CST) on tty2
No mail.
Plan:
I will study Linux during this year.
就是上面特殊字体呈现的那些地方是由 chfn 所修改出来的!
这个命令说实在的,除非是你的主机有很多的用户,否则倒真是用不着这个程序!这就有点像是bbs里面修改你“个人属性”。不过还是可以自己玩一玩!尤其是用来提醒自己相关数据。
chsh
这就是 change shell 的简写!使用方法就更简单了!
[vbird1@www ~]$ chsh [-ls]
参数:
-l :列出目前系统上面可用的 shell ,其实就是 /etc/shells 的内容!
-s :设置修改自己的 shell。
范例一:用 vbird1 的身份列出系统上所有合法的 shell,并且指定 csh 为自己的 shell
[vbird1@www ~]$ chsh -l
/bin/sh
/bin/bash
/sbin/nologin <==所谓:合法不可登录的 shell 就是这玩意!
/bin/tcsh
/bin/csh <==这就是 C shell 。
/bin/ksh
其实上面的信息就是我们在 bash 中谈到的 /etc/shells
[vbird1@www ~]$ chsh -s /bin/csh; grep vbird1 /etc/passwd
Changing shell for vbird1.
Password: <==确认身份,请输入 vbird1 的密码
Shell changed.
vbird1:x:504:505:VBird Tsai test,Dic in Ksu. Tainan,06-2727175#356,06-1234567:
/home/vbird1:/bin/csh
[vbird1@www ~]$ chsh -s /bin/bash
测试完毕后,立刻改回来!
[vbird1@www ~]$ ll $(which chsh)
-rws—x—x 1 root root 19128 May 25 2008 /usr/bin/chsh
不论是chfn与chsh,都是能够让一般用户修改/etc/passwd这个系统文件的。所以你猜猜这两个文件的权限是什么,一定是SUID的功能。看到这里,想到前面!这就是Linux的学习方法。
id
id这个命令则可以查询某人或自己的相关UID/GID等的信息,它的参数也不少,不过,都不需要记,反正使用id就全部都列出。
[root@www ~]# id [username]
范例一:查阅 root 自己的相关 ID 信息!
[root@www ~]# id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm), 6(disk),10 (wheel) context=root:system_r:unconfined_t:SystemLow-SystemHigh
上面信息其实是同一行的数据!包括会显示 UID/GID 以及支持的所有用户组!
至于后面那个 context=… 则是 SELinux 的内容,先不要理会它!
范例二:查阅一下 vbird1
[root@www ~]# id vbird1
uid=504(vbird1) gid=505(vbird1) groups=505(vbird1) context=root:system_r:
unconfined_t:SystemLow-SystemHigh
[root@www ~]# id vbird100
id: vbird100: No such user <== id 这个命令也可以用来判断系统上面有无某账号!
14.2.3 新增与删除用户组
了解了账号的新增、删除、改动与查询后,再来我们可以聊一聊用户组的相关内容了。基本上,用户组的内容都与这两个文件有关:/etc/group, /etc/gshadow。用户组的内容其实很简单,都是上面两个文件的新增、修改与删除而已,不过,如果再加上有效用户组的概念,那么newgrp与gpasswd则不可不知。
groupadd
[root@www ~]# groupadd [-g gid] [-r] 用户组名
参数:
-g :后面接某个特定的 GID ,用来直接给予某个 GID 。
-r :新建系统用户组。与 /etc/login.defs 内的 GID_MIN 有关。
范例一:新建一个用户组,名称为 group1
[root@www ~]# groupadd group1
[root@www ~]# grep group1 /etc/group /etc/gshadow
/etc/group:group1:x:702:
/etc/gshadow:group1:!::
用户组的 GID 也是会由 500 以上最大 GID+1 来决定!
曾经有些人谈到,为了让用户的UID/GID成对,他们建议新建的与用户私有组无关的其他用户组时,使用小于500以下的GID为宜。也就是说,如果要新建用户组的话,最好能够使用“groupadd -r 用户组名”的方式来新建。
groupmod
跟usermod类似,这个命令仅是在进行group相关参数的修改而已。
[root@www ~]# groupmod [-g gid] [-n group_name] 用户组名
参数:
-g :修改既有的 GID 数字;
-n :修改既有的组名。
范例一:将刚才上个命令新建的 group1 名称改为 mygroup ,GID 为 201
[root@www ~]# groupmod -g 201 -n mygroup group1
[root@www ~]# grep mygroup /etc/group /etc/gshadow
/etc/group:mygroup:x:201:
/etc/gshadow:mygroup:!::
不过,还是那句老话,不要随意改动GID,容易造成系统资源的错乱。
groupdel
groupdel自然就是在删除用户组。用法很简单:
[root@www ~]# groupdel [groupname]
范例一:将刚才的 mygroup 删除!
[root@www ~]# groupdel mygroup
范例二:若要删除 vbird1 这个用户组的话?
[root@www ~]# groupdel vbird1
groupdel: cannot remove user's primary group.
为什么 mygroup 可以删除,但是 vbird1 就不能删除呢?原因很简单,有某个账号(/etc/passwd)的初始用户组使用该用户组!如果查阅一下,你会发现在/etc/passwd 内的vbird1第四列的GID就是/etc/group内的vbird1那个组的GID,所以,当然无法删除,否则vbird1 这个用户登录系统后,就会找不到 GID,那可是会造成很大的困扰的!那么如果硬要删除 vbird1 这个用户组呢?你必须要确认/etc/passwd 内的账号没有任何人使用该用户组作为初如用户组才行。所以,你可以:
修改vbird1的GID,或者是:
删除vbird1这个用户。
gpasswd:用户组管理员功能
如果系统管理员太忙碌了,导致某些账号想要加入某个项目时找不到人帮忙,这个时候可以新建“用户组管理员”。什么是用户组管理员呢?就是让某个用户组具有一个管理员,这个用户组管理员可以管理哪些账号可以加入/移出该用户组!那要如何新建一个用户组管理员呢?就得要通过gpasswd。
关于系统管理员(root)做的动作:
[root@www ~]# gpasswd groupname
[root@www ~]# gpasswd [-A user1,…] [-M user3,…] groupname
[root@www ~]# gpasswd [-rR] groupname
参数:
若没有任何参数时,表示给予 groupname 一个密码(/etc/gshadow)。
-A :将 groupname 的主控权交由后面的用户管理(该用户组的管理员)。
-M :将某些账号加入这个用户组当中!
-r :将 groupname 的密码删除。
-R :让 groupname 的密码栏失效。
关于用户组管理员(Group administrator)做的操作:
[someone@www ~]$ gpasswd [-ad] user groupname
参数:
-a :将某位用户加入到 groupname 这个用户组当中!
-d :将某位用户删除出 groupname 这个用户组当中。
范例一:新建一个新用户组,名称为 testgroup 且用户组交由 vbird1 管理:
[root@www ~]# groupadd testgroup <==先新建用户组
[root@www ~]# gpasswd testgroup <==给这个用户组一个密码吧!
Changing the password for group testgroup
New Password:
Re-enter new password:
输入两次密码就对了!
[root@www ~]# gpasswd -A vbird1 testgroup <==加入用户组管理员为 vbird1
[root@www ~]# grep testgroup /etc/group /etc/gshadow
/etc/group:testgroup:x:702:
/etc/gshadow:testgroup:$1$I5ukIY1.$o5fmW.cOsc8.K.FHAFLWg0:vbird1:
很有趣吧!此时 vbird1 则拥有 testgroup 的主控权,身份有点像版主。
范例二:以 vbird1 登录系统,并且让他加入 vbird1, vbird3 成为 testgroup 成员
[vbird1@www ~]$ id
uid=504(vbird1) gid=505(vbird1) groups=505(vbird1) ….
看得出来,vbird1 尚未加入 testgroup 用户组。
[vbird1@www ~]$ gpasswd -a vbird1 testgroup
[vbird1@www ~]$ gpasswd -a vbird3 testgroup
[vbird1@www ~]$ grep testgroup /etc/group
testgroup:x:702:vbird1,vbird3
很有趣的一个小实验吧?我们可以让testgroup成为一个可以公开的用户组,然后新建用户组管理员,用户组管理员可以有多个。在这个案例中,我将vbird1设置为testgroup的用户组管理员,所以vbird1就可以自行增加用户组成员。然后,该用户组成员就能够使用newgrp了。
14.2.4 账号管理实例
账号管理不是随意建几个账号就算了,有时候我们需要考虑到一台主机上面可能有多个账号在协同工作。举例来说,在大学任教时,我们学校的学生是需要分组的,这些同一组的同学间必须要能够互相修改对方的数据文件,但是同时这些同学又需要保留自己的私密数据,因此直接公开主文件夹是不适宜的,那该如何是好?为此,我们下面提供几个例子来让大家思考。
任务一:单纯完成上面交代的任务,假设我们需要的账号数据如表14-2所示,你该如何实现?
表14-2
处理的方法如下所示:
先处理账号相关属性的数据:
[root@www ~]# groupadd mygroup1
[root@www ~]# useradd -G mygroup1 -c "1st user" myuser1
[root@www ~]# useradd -G mygroup1 -c "2nd user" myuser2
[root@www ~]# useradd -c "3rd user" -s /sbin/nologin myuser3
再处理账号的密码相关属性的数据:
[root@www ~]# echo "password" | passwd —stdin myuser1
[root@www ~]# echo "password" | passwd —stdin myuser2
[root@www ~]# echo "password" | passwd —stdin myuser3
要注意的地方是,myuser1与myuser2都有支援次要用户组,但该用户组不见得会存在,因此需要先手动新建它!然后 myuser3 是“不可登录系统”的账号,因此需要使用/sbin/nologin 这个 shell来给予,这样该账号就无法登录。这样是否理解啊?接下来再来讨论比较难一些的环境,如果是特定环境该如何制作?
任务二:我的用户pro1, pro2, pro3 是同一个项目计划的开发人员,我想要让这三个用户在同一个目录下面工作,但这三个用户还是拥有自己的主文件夹与基本的私有用户组。假设我要让这个项目计划在/srv/projecta目录下开发,可以如何进行?
1. 假设这三个账号都尚未新建,可先新建一个名为 projecta 的用户组,
再让这三个用户加入其次要用户组的支持即可:
[root@www ~]# groupadd projecta
[root@www ~]# useradd -G projecta -c "projecta user" pro1
[root@www ~]# useradd -G projecta -c "projecta user" pro2
[root@www ~]# useradd -G projecta -c "projecta user" pro3
[root@www ~]# echo "password" | passwd —stdin pro1
[root@www ~]# echo "password" | passwd —stdin pro2
[root@www ~]# echo "password" | passwd —stdin pro3
2. 开始新建此项目的开发目录:
[root@www ~]# mkdir /srv/projecta
[root@www ~]# chgrp projecta /srv/projecta
[root@www ~]# chmod 2770 /srv/projecta
[root@www ~]# ll -d /srv/projecta
drwxrws—- 2 root projecta 4096 Feb 27 11:29 /srv/projecta
由于此项目计划只能够给 pro1, pro2, pro3 三个人使用,所以/srv/projecta 的权限设置一定要正确才行!所以该目录组一定是projecta,但是权限怎么会是2770呢?还记得第7章谈到的SGID吧?为了让三个用户能够互相修改对方的文件,这个SGID是必须要存在的。如果连这里都能够理解,那你对账号管理已经有一定程度的概念。
但接下来有个困扰的问题发生了,假如任务一的myuser1是projecta这个项目的助理,他需要这个项目的内容,但是他不可以修改项目目录内的任何数据!那该如何是好?你或许可以这样做:
将 myuser1 加入 projecta 这个用户组的支持,但是这样会让 myuser1 具有完整的/srv/projecta的权限,myuser1是可以删除该目录下的任何数据的。这样是有问题的。
将/srv/projecta 的权限改为 2775,让 myuser1 可以进入查阅数据。但此时会发生所有其他人均可进入该目录查阅的困扰!这也不是我们要的环境。
真要命,传统的Linux权限无法针对某个个人设置专属的权限吗?其实是可以的,接下来我们就来谈谈这个功能。
14.3 主机的具体权限规划:ACL的使用
从第6章开始,我们就一直强调Linux的权限概念是非常重要的!但是传统的权限仅有三种身份(owner, group, others)搭配三种权限(r,w,x)而已,并没有办法单纯针对某一个用户或某一个组来设置特定的权限需求,例如前一小节最后的那个任务!此时就得要使用ACL这个机制。这玩意挺有趣的,下面我们就来谈一谈。
14.3.1 什么是ACL
ACL 是Access Control List 的缩写,主要的目的是提供传统的owner、group、others 的read、write、execute权限之外的具体权限设置。ACL可以针对单一用户、单一文件或目录来进行r、w、x的权限设置,对于需要特殊权限的使用状况非常有帮助。
那ACL主要可以针对哪些方面来控制权限呢?它主要可以针对几个项目:
用户(user):可以针对用户来设置权限;
用户组(group):针对用户组来设置其权限;
默认属性(mask):还可以在该目录下在新建新文件/目录时设置新数据的默认权限。
好了,再来看看如何让你的文件系统可以支持ACL。
14.3.2 如何启动 ACL
由于ACL是传统的UNIX-like操作系统权限的额外支持项目,因此要使用ACL必须要有文件系统的支持才行。目前绝大部分的文件系统都有支持ACL的功能,包括ReiserFS,EXT2/EXT3,JFS,XFS等。在我们的 CentOS 5.x 当中,默认使用 Ext3 是启动 ACL 支持的!至于查看你的文件系统是否支持ACL可以这样看:
[root@www ~]# mount <==直接查看挂载参数的功能
/dev/hda2 on / type ext3 (rw)
/dev/hda3 on /home type ext3 (rw)
其他选项鸟哥都将它省略了。假设我们只要看这两个设备,但没有看到 acl 。
[root@www ~]# dumpe2fs -h /dev/hda2 <==由 superblock 内容去查询
….(前面省略)…
Default mount options: user_xattr acl
….(后面省略)…
由mount单纯去查阅不见得可以看到实际的选项,由于目前新的distributions经常会主动加入某些默认功能,如上所示,其实 CentOS 5.x 在默认的情况下(Default mount options:)就帮你加入 acl的支持了。那如果你的系统默认不会帮你加上acl的支持呢?那你可以这样操作:
[root@www ~]# mount -o remount,acl /
[root@www ~]# mount
/dev/hda2 on / type ext3 (rw,acl)
这样就加入了!但是如果想要每次开机都生效,那就这样做:
[root@www ~]# vi /etc/fstab
LABEL=/1 / ext3 defaults,acl 1 1
如果你不确定或者是不会使用dumpe2fs查看你的文件系统,那么建议直接将上述的/etc/fstab里面的内容修改一下即可!
14.3.3 ACL 的设置技巧:getfacl,setfacl
好了,让你的文件系统启动ACL支持后,接下来该如何设置与查看ACL呢?很简单,利用这两个命令就可以了:
getfacl:取得某个文件/目录的ACL设置项目;
setfacl:设置某个目录/文件的ACL规定。
先让我们来瞧一瞧setfacl如何使用吧!
setfacl命令用法
[root@www ~]# setfacl [-bkRd] [{-m|-x} acl参数] 目标文件名
参数:
-m :设置后续的 acl 参数给文件使用,不可与 -x 合用;
-x :删除后续的 acl 参数,不可与 -m 合用;
-b :删除所有的 ACL 设置参数;
-k :删除默认的 ACL 参数,关于所谓的“默认”参数于后续范例中介绍;
-R :递归设置 acl ,亦即包括子目录都会被设置起来;
-d :设置默认 acl 参数!只对目录有效,在该目录新建的数据会引用此默认值。
上面谈到的是acl的选项功能,那么如何设置ACL的特殊权限呢?特殊权限的设置方法有很多,我们先来谈谈最常见的,就是针对单一用户的设置方式:
1. 针对特定用户的方式:
设置规定:“ u:[用户账号列表]:[rwx] ”,例如针对 vbird1 的权限规定 rx :
[root@www ~]# touch acl_test1
[root@www ~]# ll acl_test1
-rw-r—r— 1 root root 0 Feb 27 13:28 acl_test1
[root@www ~]# setfacl -m u:vbird1:rx acl_test1
[root@www ~]# ll acl_test1
-rw-r-xr—+ 1 root root 0 Feb 27 13:28 acl_test1
权限部分多了个 + ,且与原本的权限 (644) 看起来区别很大!但要如何查阅呢?
[root@www ~]# setfacl -m u::rwx acl_test1
[root@www ~]# ll acl_test1
-rwxr-xr—+ 1 root root 0 Feb 27 13:28 acl_test1
无用户列表,代表设置该文件所有者,所以上面显示 root 的权限成为 rwx 了!
上述操作为最简单的ACL设置,利用“u:用户:权限”的方式来设置。设置前请加上-m这个参数。如果一个文件设置了 ACL 参数后,它的权限部分就会多出一个+号了!但是此时你看到的权限与实际权限可能就会有点误差。那要如何查看呢?可以通过getfacl来查看。
getfacl 命令用法
[root@www ~]# getfacl filename
参数:
getfacl 的参数几乎与 setfacl 相同。所以鸟哥这里就免去了参数的说明。
请列出刚才我们设置的 acl_test1 的权限内容:
[root@www ~]# getfacl acl_test1
file: acl_test1 <==说明文件名而已。
owner: root <==说明此文件的所有者,即 ll 看到的第三用户字段
group: root <==此文件的所属用户组,亦即 ll 看到的第四用户组字段
user::rwx <==用户列表栏是空的,代表文件所有者的权限
user:vbird1:r-x <==针对 vbird1 的权限设置为 rx ,与所有者并不同!
group::r— <==针对文件用户组的权限设置仅有 r
mask::r-x <==此文件默认的有效权限 (mask)
other::r— <==其他人拥有的权限。
上面的数据非常容易查阅吧?显示的数据前面加上#的,代表这个文件的默认属性,包括文件名、文件所有者与文件所属用户组。下面出现的user、group、mask、other则是属于不同用户、用户组与有效权限(mask)的设置值。以上面的结果来看,我们刚才设置的vbird1对于这个文件具有r与x的权限。这样看得懂吗?如果看得懂的话,接下来让我们再测试其他类型的setfacl设置。
2. 针对特定用户组的方式:
设置规范:“ g:[用户组列表]:[rwx] ”,例如针对 mygroup1 的权限规范 rx :
[root@www ~]# setfacl -m g:mygroup1:rx acl_test1
[root@www ~]# getfacl acl_test1
file: acl_test1
owner: root
group: root
user::rwx
user:vbird1:r-x
group::r—
group:mygroup1:r-x <==这里就是新增的部分,多了这个用户组的权限设置。
mask::r-x
other::r—
基本上,用户组与用户的设置并没有什么太大的区别。如上所示,非常容易了解意义。不过,你应该会觉得奇怪的是,那个mask是什么东西啊?其实它有点像是“有效权限”的意思。它的意思是用户或组所设置的权限必须要存在于mask的权限设置范围内才会生效,此即有效权限(effective permission),我们举个例子来看,如下所示:
3. 针对有效权限 mask 的设置方式:
设置规定:“ m:[rwx] ”,例如针对刚才的文件规定为仅有 r :
[root@www ~]# setfacl -m m:r acl_test1
[root@www ~]# getfacl acl_test1
file: acl_test1
owner: root
group: root
user::rwx
user:vbird1:r-x #effective:r— <==vbird1+mask均存在的仅有 r 而已!
group::r—
group:mygroup1:r-x #effective:r—
mask::r—
other::r—
vbird1与mask的集合发现仅有r存在,因此vbird1仅具有r的权限而已,并不存在x权限,这就是mask的功能。我们可以通过使用mask来规定最大允许的权限,就能够避免不小心开放某些权限给其他用户或用户组了。不过,通常鸟哥都是将mask设置为rwx,然后再分别依据不同的用户/用户组去规定它们的权限就是了。
将14.2.4小节任务二中/srv/projecta这个目录,让myuser1可以进入查阅,但myuser1不具有修改的权限。
答:由于myuser1是独立的用户与用户组,而/srv是附属于/之下的,因此/srv已经具有acl的功能。通过如下的设置即可搞定:
1. 先测试看看使用 myuser1 能否进入该目录
[myuser1@www ~]$ cd /srv/projecta
-bash: cd: /srv/projecta: Permission denied <==确实不可进入!
2. 开始用 root 的身份来设置一下该目录的权限吧!
[root@www ~]# setfacl -m u:myuser1:rx /srv/projecta
[root@www ~]# getfacl /srv/projecta
file: srv/projecta
owner: root
group: projecta
user::rwx
user:myuser1:r-x <==还是要看看有没有设置成功。
group::rwx
mask::rwx
other::—-
3. 还是得要使用 myuser1 去测试看看结果!
[myuser1@www ~]$ cd /srv/projecta
[myuser1@www projecta]$ ll -a
drwxrws—-+ 2 root projecta 4096 Feb 27 11:29 . <==确实可以查询文件名
drwxr-xr-x 4 root root 4096 Feb 27 11:29 ..
[myuser1@www projecta]$ touch testing
touch: cannot touch `testing': Permission denied <==确实不可以写入!
请注意,上述的1、3步骤使用myuser1的身份,步骤2才是使用root设置。
上面的设置我们就完成了之前任务二的后续需求。接下来让我们来测试一下,如果我用 root或者是pro1的身份去/srv/projecta增加文件或目录时,该文件或目录是否能够具有ACL的设置?意思就是说,ACL的权限设置是否能够被子目录所“继承”?先试看看:
[root@www ~]# cd /srv/projecta
[root@www ~]# touch abc1
[root@www ~]# mkdir abc2
[root@www ~]# ll -d abc*
-rw-r—r— 1 root projecta 0 Feb 27 14:37 abc1
drwxr-sr-x 2 root projecta 4096 Feb 27 14:37 abc2
你可以明显发现,权限后面都没有 + ,代表这个 acl 属性并没有继承。如果你想要让 acl 在目录下面的数据都有继承的功能,如下所示。
4. 针对默认权限的设置方式:
设置规范:“ d:[ug]:用户列表:[rwx] ”
让 myuser1 在 /srv/projecta 下面一直具有 rx 的默认权限!
[root@www ~]# setfacl -m d:u:myuser1:rx /srv/projecta
[root@www ~]# getfacl /srv/projecta
file: srv/projecta
owner: root
group: projecta
user::rwx
user:myuser1:r-x
group::rwx
mask::rwx
other::—-
default:user::rwx
default:user:myuser1:r-x
default:group::rwx
default:mask::rwx
default:other::—-
[root@www ~]# cd /srv/projecta
[root@www projecta]# touch zzz1
[root@www projecta]# mkdir zzz2
[root@www projecta]# ll -d zzz*
-rw-rw——+ 1 root projecta 0 Feb 27 14:57 zzz1
drwxrws—-+ 2 root projecta 4096 Feb 27 14:57 zzz2
确实有继承。然后我们使用 getfacl 再次确认。
[root@www projecta]# getfacl zzz2
file: zzz2
owner: root
group: projecta
user::rwx
user:myuser1:r-x
group::rwx
mask::rwx
other::—-
default:user::rwx
default:user:myuser1:r-x
default:group::rwx
default:mask::rwx
default:other::—-
通过这个“针对目录来设置的默认ACL权限设置值”的选项,我们可以让这些属性继承到子目录下面,非常方便。那如果想要让 ACL 的属性全部消失又要如何处理?通过“setfacl–b文件名”即可。
14.4 用户身份切换
什么?在Linux系统当中还要做身份的变换?这是为什么?可能有下面几个原因。
使用一般账号:系统平日操作的好习惯
事实上,为了安全的缘故,一些学者都会建议你,尽量以一般身份用户来操作Linux的日常作业,等到需要设置系统环境时,才变换身份成为 root 来进行系统管理,相对比较安全,避免做错一些严重的命令,例如恐怖的“rm-rf/”(千万做不得)!
用较低权限启动系统服务
相对于系统安全,有的时候,我们必须要以某些系统账号来进行程序的执行。举例来说,Linux主机上面的一套软件,名称为 apache,我们可以额外新建一个名为 apache 的用户来启动apache软件,如此一来,如果这个程序被攻破,至少系统还不至于损坏了。
软件本身的限制
在远古时代的telnet程序中,该程序默认是不许使用root的身份登录的,telnet会判断登录者的UID,若UID为0的话,那就直接拒绝登录了。所以,你只能使用一般用户来登录Linux服务器。
此外,ssh [3]也可以设置拒绝root登录。那如果你有系统设置需求该如何是好啊?就切换身份。
由于上述考虑,所以我们都是使用一般账号登录系统的,等有需要进行系统维护或软件更新时才转为root的身份来操作。那如何让一般用户转变身份成为root呢?主要有两种方式:
以“su -”直接将身份变成 root 即可,但是这个命令却需要root 的密码,也就是说,如果你要以su变成root的话,你的一般用户就必须要有root的密码才行;
以“sudo命令”执行root的命令串,由于sudo需要事先设置妥当,且sudo需要输入用户自己的密码,因此多人共管同一台主机时,sudo要比su来得好。至少root密码不会流出去!
下面我们就来说一说su跟sudo的用法。
14.4.1 su
su是最简单的身份切换命令了,它可以进行任何身份的切换。方法如下:
[root@www ~]# su [-lm] [-c 命令] [username]
参数:
- :单纯使用 - 如“ su - ”,代表使用 login-shell 的变量文件读取方式来登录系统;
若用户名称没有加上去,则代表切换为 root 的身份。
-l :与 - 类似,但后面需要加欲切换的用户账号。也是 login-shell 的方式。
-m :-m 与 -p 是一样的,表示使用目前的环境设置,而不读取新用户的配置文件。
-c :仅进行一次命令,所以 -c 后面可以加上命令。
上面的解释当中有出现之前第11章谈过的login-shell配置文件读取方式,如果你忘记那是什么东西,请先回去第11 章瞧瞧再回来吧!这个su 的用法当中,有没有加上那个减号“–”差很多喔!因为涉及 login-shell 与 non-login shell 的变量读取方法。这里让我们以一个小例子来说明。
范例一:假设你原本是 vbird1 的身份,想要使用 non-login shell 的方式变成 root
[vbird1@www ~]$ su <==注意提示符,是 vbird1 的身份。
Password: <==这里输入 root 的密码。
[root@www vbird1]# id <==提示符的目录是 vbird1 。
uid=0(root) gid=0(root) groups=0(root),1(bin),… <==确实是 root 的身份!
[root@www vbird1]# env | grep 'vbird1'
USER=vbird1
PATH=/usr/local/bin:/bin:/usr/bin:/home/vbird1/bin <==这个影响最大!
MAIL=/var/spool/mail/vbird1 <==收到的 mailbox 是 vbird1
PWD=/home/vbird1 <==并非 root 的主文件夹
LOGNAME=vbird1
虽然你的 UID 已经是具有 root 的身份,但是看到上面的输出信息吗?
还是有一堆变量为原本 vbird1 的身份,所以很多数据还是无法直接利用。
[root@www vbird1]# exit <==这样可以离开 su 的环境!
单纯使用“su”切换成为 root 的身份,读取的变量设置方式为non-login shell 的方式,这种方式下很多原本的变量不会被改变,尤其是我们之前谈过很多次的PATH这个变量,由于没有改变成为root的环境(一堆 /sbin、/usr/sbin 等目录都没有被包含进来),因此很多 root 惯用的命令就只能使用绝对路径来执行了。其他的还有MAIL这个变量,你输入mail时,收到的邮件竟然还是vbird1的,而不是root本身的邮件。是否觉得很奇怪,所以切换身份时,请务必使用如下的范例二:
范例二:使用 login shell 的方式切换为 root 的身份并查看变量
[vbird1@www ~]$ su -
Password: <==这里输入 root 密码。
[root@www ~]# env | grep root
USER=root
MAIL=/var/spool/mail/root
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
PWD=/root
HOME=/root
LOGNAME=root
了解区别了吧?下次切换成为 root 时,记得最好使用 su – 。
[root@www ~]# exit <==这样可以离开 su 的环境!
上述的做法是让用户的身份变成root并开始操作系统,如果想要离开root的身份则得要利用exit离开才行。那我如果只是想要执行一个只有root才能进行的命令,且执行完毕就恢复原本的身份呢?那就可以加上-c这个参数。请参考下面范例三!
范例三:vbird1 想要执行“ head -n 3 /etc/shadow ”一次,且已知 root 密码
[vbird1@www ~]$ head -n 3 /etc/shadow
head: cannot open `/etc/shadow' for reading: Permission denied
[vbird1@www ~]$ su - -c "head -n 3 /etc/shadow"
Password: <==这里输入 root 密码。
root:$1$/30QpEWEBEZXRD0bh6rAABCEQD.BAH0:14126:0:99999:7:::
bin:*:14126:0:99999:7:::
daemon:*:14126:0:99999:7:::
[vbird1@www ~]$ <==注意看,身份还是 vbird1 。继续使用旧的身份进行系统操作!
由于/etc/shadow权限的关系,该文件仅有root可以查阅。为了查阅该文件,所以我们必须要使用 root 的身份工作。但我只想要进行一次该命令而已,此时就使用类似上面的语法。如果我是 root或者是其他人,想要更改成为某些特殊账号,可以使用如下的方法来切换。
范例四:原本是 vbird1 这个用户,想要变换身份成为 dmtsai 时
[vbird1@www ~]$ su -l dmtsai
Password: <==这里输入 dmtsai 密码。
[dmtsai@www ~]$ su -
Password: <==这里输入 root 密码。
[root@www ~]# id sshd
uid=74(sshd) gid=74(sshd) groups=74(sshd) … <==确实存在此人
[root@www ~]# su -l sshd
This account is currently not available. <==竟然说此人无法切换
[root@www ~]# finger sshd
Login: sshd Name: Privilege-separated SSH
Directory: /var/empty/sshd Shell: /sbin/nologin
[root@www ~]# exit <==离开第二次的 su
[dmtsai@www ~]$ exit <==离开第一次的 su
[vbird1@www ~]$ exit <==这才是最初的环境!
su就这样简单地介绍完毕,总结一下它的用法是这样的:
若要完整地切换到新用户的环境,必须要使用“su -username”或“su – l username”,才会连同PATH/USER/MAIL等变量都转成新用户的环境;
如果仅想要执行一次 root 的命令,可以利用“su - -c"命令串"”的方式来处理;
使用root切换成为任何用户时,并不需要输入新用户的密码。
虽然使用su很方便,不过缺点是,当我的主机是多人管理的环境时,如果大家都要使用su来切换成为root的身份,那么不就每个人都得要知道root的密码,这样密码太多人知道可能会流出去,很不妥当呢!怎办?通过sudo来处理即可!
14.4.2 sudo
相对于su需要了解新切换的用户密码(经常是需要root的密码),sudo的执行则仅需要自己的密码即可!甚至可以设置不需要密码即可执行sudo呢!由于sudo可以让你以其他用户的身份执行命令(通常是使用 root 的身份来执行命令),因此并非所有人都能够执行 sudo,而是仅有/etc/sudoers内的用户才能够执行sudo这个命令。说得这么神奇,下面就来瞧瞧sudo如何使用。
sudo的命令用法
由于一开始系统默认仅有root可以执行sudo,因此下面的范例我们先以root的身份来执行,等到谈到visudo时,再以一般用户来讨论其他sudo的用法。sudo的语法如下:
[root@www ~]# sudo [-b] [-u 新用户账号]
参数:
-b :将后续的命令让系统自行执行,而不与目前的 shell 产生影响。
-u :后面可以接欲切换的用户,若无此项则代表切换身份为 root 。
范例一:你想要以 sshd 的身份在 /tmp 下面新建一个名为 mysshd 的文件
[root@www ~]# sudo -u sshd touch /tmp/mysshd
[root@www ~]# ll /tmp/mysshd
-rw-r—r— 1 sshd sshd 0 Feb 28 17:42 /tmp/mysshd
特别留意,这个文件的权限是由 sshd 所新建的。
范例二:你想要以 vbird1 的身份新建 ~vbird/www 并于其中新建 index.html 文件
[root@www ~]# sudo -u vbird1 sh -c "mkdir~vbird1/www; cd~vbird1/www; \
> echo 'This is index.html file' > index.html"
[root@www ~]# ll -a~vbird1/www
drwxr-xr-x 2 vbird1 vbird1 4096 Feb 28 17:51 .
drwx——— 5 vbird1 vbird1 4096 Feb 28 17:51 ..
-rw-r—r— 1 vbird1 vbird1 24 Feb 28 17:51 index.html
要注意,新建者的身份是 vbird1 ,且我们使用 sh -c "一串命令" 来执行。
sudo可以让你切换身份来进行某项任务,例如上面的两个范例。范例一中,我们的root使用sshd 的权限去进行某项任务。要注意,因为我们无法使用“su -sshd”去切换系统账号(因为系统账号的shell是/sbin/nologin),这个时候sudo真是太好用了。立刻以sshd的权限在/tmp下面新建文件,查阅一下文件权限你就了解意义啦!至于范例二则更使用多重命令串(通过分号;来延续命令进行),使用 sh -c 的方法来执行一连串的命令,如此确实很方便!
但是sudo默认仅有root能使用啊!为什么呢?因为sudo的执行是这样的流程:
1.当用户执行sudo时,系统于/etc/sudoers文件中查找该用户是否有执行sudo的权限;
2.若用户具有可执行sudo的权限后,便让用户输入用户自己的密码来确认;
3.若密码输入成功,便开始进行sudo后续接的命令(但root执行sudo时不需要输入密码);
4.若欲切换的身份与执行者身份相同,那也不需要输入密码。
所以说,sudo执行的重点是,能否使用sudo必须要看/etc/sudoers的设置值,而可使用sudo的是通过输入用户自己的密码来执行后续的命令串。由于能否使用与/etc/sudoers有关,所以我们当然要去编辑 sudoers 文件。不过,因为该文件的内容是有一定的规定的,因此直接使用vi去编辑是不好的。此时,我们得要通过visudo去修改这个文件。
visudo与/etc/sudoers
从上面的说明我们可以知道,除了root之外的其他账号,若想要使用sudo执行属于root的权限命令,则 root需要先使用visudo去修改/etc/sudoers,让该账号能够使用全部或部分的root命令功能。为什么要使用visudo呢?这是因为/etc/sudoers是有语法的,如果设置错误那会造成无法使用sudo命令的不良后果,因此才会使用visudo去修改,并在结束离开修改界面时,系统会去检验/etc/sudoers的语法。
一般来说,visudo的设置方式有几种简单的方法,下面我们以几个简单的例子来分别说明:I.单一用户可进行root所有命令与sudoers文件语法
假如我们要让vbird1这个账号可以使用root的任何命令,那么可以简单地这样进行修改即可:
[root@www ~]# visudo
…(前面省略)…
root ALL=(ALL) ALL <==找到这一行,大约在 76 行左右
vbird1 ALL=(ALL) ALL <==这一行是你要新增的!
…(前面省略)…
有趣吧?其实visudo只是利用vi将/etc/sudoers文件调出来进行修改而已,所以这个文件就是/etc/sudoerds。这个文件的设置其实很简单,如上面所示,如果你找到 76 行(有 root 设置的那行)左右,看到的数据就是:
用户账号 登录者的来源主机名=(可切换的身份) 可执行的命令
root ALL=(ALL) ALL <==这是默认值
上面这一行的四个参数意义是:
1.用户账号:系统的哪个账号可以使用sudo这个命令,默认为root这个账号。
2.登录者的来源主机名:这个账号由哪台主机连接到本Linux主机,意思是这个账号可能是由哪一台网络主机连接过来的,这个设置值可以指定客户端计算机(信任用户的意思)。默认值 root 可来自任何一台网络主机。
3.可切换的身份:这个账号可以切换成什么身份来执行后续的命令,默认root可以切换成任何人。
4.可执行的命令:这个命令请务必使用绝对路径编写。默认root可以切换任何身份且进行任何命令。
那个ALL是特殊的关键字,代表任何身份、主机或命令的意思。所以,我想让vbird1可以进行任何身份的任何命令,就如同上面特殊字体写的那样,其实就是复制上述默认值那一行,再将root改成vbird1即可。此时vbird1不论来自哪台主机登录,他可以变换身份成为任何人,且可以进行系统上面的任何命令。修改完请保存后离开vi,并以vbird1登录系统后,进行如下的测试看看:
[vbird1@www ~]$ tail -n 1 /etc/shadow <==注意!身份是 vbird1
tail: cannot open `/etc/shadow' for reading: Permission denied
因为不是 root 嘛!所以当然不能查询 /etc/shadow
[vbird1@www ~]$ sudo tail -n 1 /etc/shadow <==通过 sudo
We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:
1) Respect the privacy of others. <==这里仅是一些说明与警示选项
2) Think before you type.
3) With great power comes great responsibility.
Password: <==注意啊!这里输入的是“ vbird1 自己的密码 ”
pro3:$1$GfinyJgZ$9J8IdrBXXMwZIauANg7tW0:14302:0:99999:7:::
看!vbird1 竟然可以查询 shadow !
注意到了吧?vbird1输入自己的密码就能够执行root的命令。所以,系统管理员当然要了解vbird1 这个用户的“操守”才行!否则随便设置一个用户,他恶搞系统怎办?另外,一个一个设置太麻烦了,能不能使用用户组的方式来设置呢?参考下面的方式。
II.利用用户组以及免密码的功能处理visudo
我们在本章前面曾经新建过 pro1,pro2,pro3,这三个用户能否通过用户组的功能让这三个人可以管理系统?可以,而且很简单!同样我们使用实际案例来说明:
[root@www ~]# visudo <==同样,请使用 root 先设置
….(前面省略)….
%wheel ALL=(ALL) ALL <==大约在 84 行左右,请将这行的 # 去掉!
在最左边加上 % ,代表后面接的是一个“用户组”之意!改完请保存后离开
[root@www ~]# usermod -a -G wheel pro1 <==将 pro1 加入 wheel 的支持
上面的设置值会造成任何加入wheel这个用户组的用户就能够使用sudo切换任何身份来操作任何命令。你当然可以将 wheel 换成你自己想要的用户组名。接下来,请分别切换身份成为pro1及pro2试看看sudo的运行。
[pro1@www ~]$ sudo tail -n 1 /etc/shadow <==注意身份是 pro1
….(前面省略)….
Password: <==输入 pro1 密码。
pro3:$1$GfinyJgZ$9J8IdrBXXMwZIauANg7tW0:14302:0:99999:7:::
[pro2@www ~]$ sudo tail -n 1 /etc/shadow <==注意身份是 pro2
Password:
pro2 is not in the sudoers file. This incident will be reported.
仔细看错误信息它是说这个 pro2 不在 /etc/sudoers 的设置中!
这样理解用户组了吧?如果你想要让pro3也支持这个sudo的话,不需要重新使用visudo,只要利用usermod去修改pro3的用户组支持,让wheel也支持pro3的话,那他就能够进行sudo。简单吧!不过,既然我们都信任这些 sudo 的用户了,能否提供不需要密码即可使用sudo呢?就通过如下的方式:
[root@www ~]# visudo <==同样,请使用 root 先设置
….(前面省略)….
%wheel ALL=(ALL) NOPASSWD: ALL <==大约在 87 行左右,请将 # 去掉!
在最左边加上 % ,代表后面接的是一个“用户组”之意!改完请保存后离开
重点是那个NOPASSWD。该关键字是免除密码输入的意思。
III.有限制的命令操作
上面两点都会让用户能够利用 root 的身份进行任何事情,这样总是不太好。如果我想要让用户仅能够进行部分系统任务,例如,系统上面的myuser1仅能够帮root修改其他用户的密码时,即当用户仅能使用passwd这个命令帮忙root修改其他用户的密码时,你该如何编写呢?可以这样做:
[root@www ~]# visudo <==注意是 root 身份
myuser1 ALL=(root) /usr/bin/passwd <==最后命令务必用绝对路径
上面的设置值指的是myuser1可以切换成为root使用passwd这个命令。其中要注意的是:命令字段必须要填写绝对路径才行,否则visudo会出现语法错误的状况发生。此外,上面的设置是有问题的,我们使用下面的命令操作来让你更好地理解:
[myuser1@www ~]$ sudo passwd myuser3 <==注意,身份是 myuser1
Password: <==输入 myuser1 的密码
Changing password for user myuser3. <==改的是 myuser3 的密码。这样是正确的
New UNIX password:
Retype new UNIX password:
passwd: all authentication tokens updated successfully.
[myuser1@www ~]$ sudo passwd
Changing password for user root. <==见鬼!怎么会去改 root 的密码?
我们竟然让root的密码被myuser3给改变了!下次root回来竟无法登录系统,欲哭无泪。怎办?所以我们必须要限制用户的命令参数。修改的方法为将上述的那行修改先:
[root@www ~]# visudo <==注意是 root 身份
myuser1 ALL=(root) !/usr/bin/passwd, /usr/bin/passwd [A-Za-z]*, \
!/usr/bin/passwd root
由于屏幕一行写不完,我将这行写成两行,所以上面第一行最后加上反斜杠。加上惊叹号“!”代表“不可执行”的意思。因此上面这一行会变成可以执行“passwd任意字符”,但是“passwd”与“passwd root”这两个命令例外。如此一来myuser1 就无法改变root的密码了。这样这位用户可以具有root的能力帮助你修改其他用户的密码,而且也不能随意改变root的密码。
IV.通过别名设置visudo
如上述第三点,如果我有15个用户需要加入刚才的管理员行列,那么我是否要将上述那长长的设置写入15行啊?而且如果想要修改命令或者是新增命令时,那我每行都需要重新设置,很麻烦。有没有更简单的方式?是有的!通过别名即可!我们visudo的别名可以是命令别名、账户别名、主机别名等。不过这里我们仅介绍帐户别名,其他的设置值有兴趣的话,可以自行玩玩!
假设我的pro1, pro2, pro3与myuser1, myuser2要加入上述的密码管理员的sudo列表中,那我可以新建一个账户别名称为ADMPW的名称,然后将这个名称处理一下即可。处理的方式如下:
[root@www ~]# visudo <==注意是 root 身份
User_Alias ADMPW = pro1, pro2, pro3, myuser1, myuser2
Cmnd_Alias ADMPWCOM = !/usr/bin/passwd, /usr/bin/passwd [A-Za-z]*, \
!/usr/bin/passwd root
ADMPW ALL=(root) ADMPWCOM
我通过 User_Alias 新建一个新账号,这个账号名称一定要使用大写字符来处理,包括Cmnd_Alias(命令别名)、Host_Alias(来源主机名别名)都需要使用大写字符。这个ADMPW代表后面接的那些实际账号。而该账号能够进行的命令就如同ADMPWCOM后面所指定的。上表最后一行则写入这两个别名(账号与命令别名),将来要修改时,我只要修改User_Alias以及Cmnd_Alias这两行即可!设置方面会比较简单而且有弹性。
V.sudo的时间间隔问题
或许你已经发现了,那就是,如果我使用同一个账号在短时间内重复操作sudo来运行命令的话,在第二次执行sudo时,并不需要输入自己的密码,sudo还是会正确运行。为什么呢?第一次执行sudo需要输入密码,是担心由于用户暂时离开,但有人跑来使用你的账号之故,所以需要你输入一次密码重新确认一次身份。
两次执行 sudo 的间隔在五分钟内,那么再次执行 sudo 时就不需要再次输入密码了,这是因为系统相信你在五分钟内不会离开你的作业,所以执行 sudo的是同一个人。真是很人性化的设计啊!不过如果两次sudo操作的间隔超过5分钟,那就得要重新输入一次你的密码了 [4]。
另外要注意的是,因为使用一般账号时,理论上不会使用到/sbin, /usr/sbin 等目录内的命令,所以$PATH变量不会含有这些目录,因此很多管理命令需要使用绝对路径来执行比较妥当。
VI.sudo搭配su的使用方式
很多时候我们需要大量执行很多root的工作,所以一直使用sudo觉得很烦。那有没有办法使用sudo搭配su,一口气将身份转为root,而且还用用户自己的密码来变成root呢?是有的,而且方法很简单。我们新建一个ADMINS账户别名,然后这样做:
[root@www ~]# visudo
User_Alias ADMINS = pro1, pro2, pro3, myuser1
ADMINS ALL=(root) /bin/su –
接下来,上述的 pro1, pro2, pro3, myuser1 这四个人,只要输入“sudo su-”并且输入自己的密码后,立刻变成root的身份,不但root密码不会外泄,用户的管理也变得非常方便。这也是多人共管一部主机时经常使用的技巧呢!这样管理确实方便,不过还是要强调一下大前提,那就是这些你加入的用户全部都是你能够信任的用户。
14.5 用户的特殊shell 与PAM 模块
我们前面一直谈到的大多是一般身份用户与系统管理员(root)的相关操作,而且大多是讨论关于可登录系统的账号来说。那么换个角度想,如果我今天想要新建的是一个仅能使用 mail server 相关邮件服务的账号,而该账号并不能登录Linux主机呢?如果不能给予该账号一个密码,那么该账号就无法使用系统的各项资源,当然也包括mail的资源,而如果给予一个密码,那么该账号就可能可以登录Linux主机。所以,下面让我们来谈一谈这些有趣的话题。
另外,在本章之前谈到过/etc/login.defs 文件中,关于密码长度应该默认是 5 个字符串长度,但是我们上面也谈到,该设置值已经被PAM模块所替代了,那么PAM是什么?为什么它可以影响我们用户的登录呢?这里也要来谈谈。
14.5.1 特殊的shell, /sbin/nologin
在本章一开头的 passwd 文件结构里面我们就谈过系统账号,系统账号的 shell 就是使用/sbin/nologin,重点在于系统账号是不需要登录的!所以我们就给他这个无法登录的合法shell。使用了这个shell的用户即使有了密码,你想要登录时他也无法登录,因为会出现如下的信息:
This account is currently not available.
我们所谓的“无法登录”指的仅是这个用户无法使用bash或其他shell来登录系统而已,并不是说这个账号就无法使用其他的系统资源。举例来说,各个系统账号中,打印作业由lp这个账号在管理,WWW服务由apache这个账号在管理,他们都可以进行系统程序的工作,但是就是无法登录主机而已。
换个角度来想,如果我的Linux主机提供的是邮件服务,所以说,在这台Linux主机上面的账号,其实大部分都是用来接收主机的信件而已,并不需要登录主机。这个时候,我们就可以考虑让单纯使用 mail 的账号以/sbin/nologin 作为他们的 shell,这样,最起码当我的主机被尝试想要登录系统以取得shell环境时,可以拒绝该账号。
另外,如果我想要让某个具有/sbin/nologin 的用户知道,他们不能登录主机时,其实我可以新建“/etc/nologin.txt”这个文件,并且在这个文件内说明不能登录的原因,那么下次当这个用户想要登录系统时,屏幕上出现的就会是/etc/nologin.txt这个文件的内容,而不是默认的内容了!
当用户尝试利用纯mail账号(例如myuser3)时,利用/etc/nologin.txt告知用户不要利用该账号登录系统。
答:直接以vi编辑该文件,内容可以是这样:
[root@www ~]# vi /etc/nologin.txt
This account is system account or mail account.
Please DO NOT use this account to login my Linux server.
想要测试时,可以使用myuser3(此账号的shell是/sbin/nologin)来测试。
[root@www ~]# su - myuser3
This account is system account or mail account.
Please DO NOT use this account to login my Linux server.
[root@www ~]#
结果会发现与原本的默认信息不一样了。
14.5.2 PAM 模块简介
在过去,我们想要对一个用户进行认证(authentication),得要求用户输入账号密码,然后通过自行编写的程序来判断该账号密码是否正确。也因为如此,我们经常得使用不同的机制来判断账号密码,所以弄得一台主机上面拥有多个各别的认证系统,也造成账号密码可能不同步的验证问题,为了解决这个问题因此有了 PAM(Pluggable Authentication Modules,嵌入式模块)的机制!
PAM 可以说是一套应用程序编程接口( ApplicationProgramming Interface, API),它提供了一连串的验证机制,只要用户将验证阶段的需求告知PAM后,PAM就能够回报用户验证的结果(成功或失败)。由于PAM仅是一套验证的机制,又可以提供给其他程序所调用,因此不论你使用什么程序,都可以使用PAM来进行验证,如此一来,就能够让账号密码或者是其他方式的验证具有一致的结果。也让程序员方便处理验证的问题了 [5]。
图14-3 PAM模块与其他程序的相关性
如图14-3所示,PAM是一个独立的API存在,只要任何程序有需求时,可以向PAM发出验证要求的通知,PAM经过一连串的验证后,将验证的结果回报给该程序,然后该程序就能够利用验证的结果来进行可登录或显示其他无法使用的信息。这也就是说,你可以在写程序的时候将PAM模块的功能加入,就能够利用PAM的验证功能。因此目前很多程序都会利用PAM。所以我们才要来学习它。
PAM用来进行验证的数据称为模块(Modules),每个PAM模块的功能都不太相同。举例来说,还记得我们在本章使用passwd命令时,如果随便输入字典上面找的到的字符串,passwd就会回报错误信息了!这是为什么呢?这就是PAM的pam_cracklib.so模块的功能!它能够判断该密码是否在字典里面,并回报给密码修改程序,此时就能够了解你的密码强度了。
所以,当你有任何需要判断是否在字典当中的密码字符串时,就可以使用pam_cracklib.so这个模块来验证,并根据验证的回报结果来编写你的程序呢。这样说,可以理解PAM的功能了吧?没错!PAM的模块也是很重要的一环!
14.5.3 PAM 模块设置语法
PAM通过一个与程序相同文件名的配置文件来进行一连串的认证分析需求。我们同样以passwd这个命令调用PAM。当你执行passwd后,这个程序调用PAM的流程是:
1.用户开始执行/usr/bin/passwd这支程序,并输入密码;
2.passwd调用PAM模块进行验证;
3.PAM模块会到/etc/pam.d/中找寻与程序(passwd)同名的配置文件;
4.依据/etc/pam.d/passwd内的设置,引用相关的PAM模块逐步进行验证分析;
5.将验证结果(成功、失败以及其他信息)回传给passwd这个程序;
6.passwd 这支程序会根据 PAM 回传的结果决定下一个操作(重新输入新密码或者通过验证!)
从上面的说明我们会知道重点其实是/etc/pam.d/里面的配置文件,以及配置文件所调用的 PAM模块进行的验证工作!既然一直谈到passwd这个密码修改命令,那我们就来看看/etc/pam.d/passwd这个配置文件的内容是怎样的吧!
[root@www ~]# cat /etc/pam.d/passwd
%PAM-1.0 <==PAM版本的说明而已!
auth include system-auth <==每一行都是一个验证的过程
account include system-auth
password include system-auth
验证类型 控制标准 PAM 模块与该模块的参数
在这个配置文件当中,除了第一行声明 PAM 版本之外,其他任何“#”开头的都是批注,而每一行都是一个独立的验证流程,每一行可以区分为三个字段,分别是验证类别(type)、控制标准(flag)、PAM的模块与该模块的参数。下面我们先来谈谈验证类别与控制标准这两项数据吧!
您会发现在上面出现的是“include(包括)”这个关键字,它代表的是调用后面的文件来作为这个类别的验证,所以,上述的每一行都要重复调用/etc/pam.d/system-auth 那个文件来进行验证!
第一个字段:验证类型(Type)
验证类型主要分为四种,分别说明如下:
auth
是authentication(认证)的缩写,所以这种类型主要用来检验用户的身份验证,这种类型通常是需要密码来检验的,所以后续接的模块是用来检验用户的身份。
account
account(账号)则大部分是在进行 authorization(授权),这种类型则主要在检验用户是否具有正确的权限,举例来说,当你使用一个过期的密码来登录时,当然就无法正确登录了。
session
session是会议期间的意思,所以session管理的就是用户在这次登录(或使用这个命令)期间PAM所给予的环境设置。在这个类型通常用于记录用户登录与注销时的信息。例如,如果你经常使用su或者是sudo命令的话,那么应该可以在/var/log/secure里面发现很多关于pam的说明,而且记载的数据是“session open, session close”的信息!
password
password 就是密码。所以这种类别主要用于提供验证的修订工作,举例来说,就是修改/更改密码。
这四个验证的类型通常是有顺序的,不过也有例外就是了。会有顺序的原因是,我们总是得要先验证身份( auth )后,系统才能够通过用户的身份给予适当的授权与权限设置(account),而且登录与注销期间的环境才需要设置,也才需要记录登录与注销的信息(session)。如果在运行期间需要更改密码时,才给予password的类型。这样说起来,自然是需要有点顺序吧!
第二个字段:验证的控制标志(control flag)
那么“验证的控制标志”(control flag)又是什么?简单地说,它就是“验证通过的标准”。
这个字段在管控该验证的放行方式,主要也分为四种控制方式:
required
此验证若成功则带有success(成功)的标志,若失败则带有failure的标志,但不论成功或失败都会继续后续的验证流程。由于后续的验证流程可以继续进行,因此相当有利于数据的登录日志(log),这也是PAM最常使用required的原因。
requisite
若验证失败则立刻回报原程序 failure 的标志,并终止后续的验证流程。若验证成功则带有success的标志并继续后续的验证流程。这个项目与required 最大的区别就在于失败的时候还要不要继续验证下去。由于 requisite 是失败就终止,因此失败时所产生的PAM信息就无法通过后续的模块来记录了。
sufficient
若验证成功则立刻回传 success 给原程序,并终止后续的验证流程;若验证失败则带有 failure 标志并继续后续的验证流程。这与requisits刚好相反!
optional
这个模块控件目的大多是在显示信息而已,并不是用在验证方面的。
如果将这些控制标志以图示的方式配合成功与否的条件绘图,如图14-4所示。
图14-4 PAM 控制标志所造成的回报流程
程序运行过程中遇到验证时才会去调用PAM,而PAM验证又分很多类型与控制,不同的控制标志所回报的信息并不相同。如图14-4所示,requisite(失败)就回报了并不会继续,而sufficient则是成功就回报了也不会继续。至于验证结束后所回报的信息通常是“succes或failure”而已,后续的流程还需要该程序的判断来继续执行才行。
14.5.4 常用模块简介
谈完了配置文件的语法后,现在让我们来查阅一下CentOS 5.x提供的PAM默认文件的内容是什么吧!由于我们经常需要通过各种方式登录(login)系统,因此就来看看登录所需要的PAM流程为何:
[root@www ~]# cat /etc/pam.d/login
%PAM-1.0
auth [user_unknown=ignore success=ok ignore=ignore default=bad] pam_securetty.so
auth include system-auth
account required pam_nologin.so
account include system-auth
password include system-auth
pam_selinux.so close should be the first session rule
session required pam_selinux.so close
session include system-auth
session required pam_loginuid.so
session optional pam_console.so
pam_selinux.so open should only be followed by sessions…
session required pam_selinux.so open
session optional pam_keyinit.so force revoke
我们可以看到,其实 login 也调用多次的 system-auth ,所以下面列出该配置文件
[root@www ~]# cat /etc/pam.d/system-auth
%PAM-1.0
This file is auto-generated.
User changes will be destroyed the next time authconfig is run.
auth required pam_env.so
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 500 quiet
auth required pam_deny.so
account required pam_unix.so
account sufficient pam_succeed_if.so uid < 500 quiet
account required pam_permit.so
password requisite pam_cracklib.so try_first_pass retry=3
password sufficient pam_unix.so md5 shadow nullok try_first_pass use_authtok
password required pam_deny.so
session optional pam_keyinit.so revoke
session required pam_limits.so
session [success=1 default=ignore] pam_succeed_if.so service in crond quiet \
use_uid
session required pam_unix.so
上面使用了非常多的 PAM 模块,每个模块的功能都不太相同,详细的模块情报可以在你的系统中找到:
/etc/pam.d/*:每个程序个别的PAM配置文件;
/lib/security/*:PAM模块文件的实际放置目录;
/etc/security/*:其他PAM环境的配置文件;
/usr/share/doc/pam-*/:详细的PAM说明文件。
例如鸟哥使用未更新过的 CentOS 5.2,pam_nologin 说明文档在:/usr/share/doc/pam 0.99.6.2/txts/README.pam_nologin。你可以自行查阅该模块的功能。鸟哥这里仅简单介绍几个较常使用的模块,详细的信息还得要你努力查阅参考书呢!
pam_securetty.so
限制系统管理员(root)只能够从安全的(secure)终端机登录。那什么是终端机?例如tty1, ty2等就是传统的终端机设备名称。那么安全的终端机设置呢?就写在/etc/securetty这个文件中。你可以查阅一下该文件,就知道为什么root可以从tty1~tty7登录,但却无法通过telnet登录Linux主机了!
pam_nologin.so
这个模块可以限制一般用户是否能够登录主机之用。当/etc/nologin这个文件存在时,则所有一般用户均无法再登录系统了!若/etc/nologin存在,则一般用户在登录时,在他们的终端机上会将该文件的内容显示出来。所以,正常的情况下,这个文件应该是不能存在于系统中的。但这个模块对root以及已经登录系统中的一般账号并没有影响。
pam_selinux.so
SELinux是个针对程序来进行详细管理权限的功能,SELinux我们会在第17章的时候再来详细谈论。由于SELinux会影响到用户执行程序的权限,因此我们利用PAM模块,将SELinux暂时关闭,等到验证通过后再予以启动!
pam_console.so
当系统出现某些问题,或者是某些时刻你需要使用特殊的终端接口(例如RS232之类的终端连接设备)登录主机时,这个模块可以帮助处理一些文件权限的问题,让用户可以通过特殊终端接口(console)顺利登录系统。
pam_loginuid.so
我们知道系统账号与一般账号的UID是不同的。一般账号UID均大于500才合理。因此,为了验证用户的UID真的是我们所需要的数值,可以使用这个模块来进行规范!
pam_env.so
用来设置环境变量的一个模块,如果你有需要额外的环境变量设置,可以参考/etc/security/pam_env.conf这个文件的详细说明。
pam_UNIX.so
这是个很复杂且重要的模块,这个模块可以用于验证阶段的认证功能,可以用于授权阶段的账号许可证管理,可以用于会议阶段的日志文件记录等,甚至也可以用于密码更新阶段的检验。非常丰富的功能!这个模块在早期使用得相当频繁。
pam_cracklib.so
可以用来检验密码的强度!包括密码是否在字典中,密码输入几次都失败就断掉此次连接等功能,都是这模块提供的。
pam_limits.so
还记得我们在第11章谈到的ulimit吗?其实那就是这个模块提供的能力!还有更多详细的设置可以参考/etc/security/limits.conf内的说明。
了解了这些模块的大致功能后,言归正传,讨论一下login的PAM验证机制流程。
1.验证阶段(auth):首先,会先经过 pam_securetty.so 判断,如果用户是 root 时,则会参考/etc/securetty的设置;接下来经过pam_env.so设置额外的环境变量;再通过pam_UNIX.so检验密码,若通过则回报login程序;若不通过则继续往下以pam_succeed_if.so判断UID是否大于500,若小于500则回报失败,否则再往下以pam_deny.so拒绝连接。
2.授权阶段(account):先以 pam_nologin.so 判断/etc/nologin 是否存在,若存在则不许一般用户登录;接下来以pam_UNIX进行账号管理,再以pam_succeed_if.so判断UID是否小于500,若小于500则不记录登录信息。最后以pam_permit.so允许该账号登录。
3.密码阶段(password):先以pam_cracklib.so设置密码仅能尝试错误3次;接下来以pam_UNIX.so通过md5,shadow等功能进行密码检验,若通过则回报login程序,若不通过则以pam_deny.so拒绝登录。
4.会议阶段(session):先以pam_selinux.so暂时关闭SELinux;使用pam_limits.so设置好用户能够操作的系统资源;登录成功后开始记录相关信息在登录文件中;以 pam_loginuid.so 设置不同的UID权限;打开pam_selinux.so的功能。
总之,就是依据验证类型( type )来看,然后先由 login 的设置值去查阅,如果出现“includesystem-auth”就转到 system-auth 文件中的相同类型,去取得额外的验证流程就是了。然后再到下一个验证类型,最终将所有的验证跑完,就结束这次的PAM验证了。
经过这样的验证流程,现在你知道为什么/etc/nologin会有问题,也会知道为何你使用一些远程联机机制时,老是无法使用root登录的问题了吧?没错!这都是PAM模块提供的功能。
为什么root无法以telnet直接登录系统,但是却能够使用ssh直接登录?
答:一般来说,telnet会引用login的PAM模块,而login的验证阶段会有/etc/securetty的限制。由于远程连接属于pts/n(n为数字)的动态终端机接口设备名称,并没有写入到/etc/securetty,因此root无法以telnet登录远程主机。至于ssh使用的是/etc/pam.d/sshd这个模块,你可以查阅一下该模块,由于该模块的验证阶段并没有加入pam_securetty,因此就没有/etc/securetty的限制!故可以从远程直接联机到服务器端。
另外,关于telnet与ssh的详细说明,请参考鸟哥的Linux私房菜之服务器篇。
14.5.5 其他相关文件
除了前一小节谈到的/etc/securetty会影响到root可登录的安全终端机,/etc/nologin会影响到一般用户是否能够登录的功能之外,我们也知道 PAM 相关的配置文件在/etc/pam.d 中,说明文件在/usr/share/doc/pam-(版本)中,模块实际在/lib/security/中。那么还有没有相关的PAM文件呢?是有的,主要都在/etc/security这个目录内!我们下面介绍几个可能会用到的配置文件。
limits.conf
我们在第11章谈到的ulimit功能中,除了修改用户的~/.bashrc配置文件之外,其实系统管理员可以统一通过 PAM 来管理的!那就是/etc/security/limits.conf 这个文件的设置了。这个文件的设置很简单,你可以自行参考一下该文件内容。我们这里仅作简单的介绍:
范例一:vbird1 这个用户只能新建 100MB 的文件,且大于 90MB 会警告
[root@www ~]# vi /etc/security/limits.conf
vbird1 soft fsize 90000
vbird1 hard fsize 100000
账号 限制依据限制项目 限制值
第一字段为账号,或者是用户组!若为用户组则前面需要加上 @ ,例如 @projecta
第二字段为限制的依据,是严格(hard)或者警告(soft)
第三字段为相关限制,此例中限制文件容量
第四字段为限制的值,在此例中单位为 KB
若以 vbird1 登录后,进行如下的操作则会有相关的限制出现!
[vbird1@www ~]$ ulimit -a
….(前面省略)….
file size (blocks, -f) 90000
….(后面省略)….
[vbird1@www ~]$ dd if=/dev/zero of=test bs=1M count=110
File size limit exceeded
[vbird1@www ~]$ ll -k test
-rw-rw-r— 1 vbird1 vbird1 90000 Mar 4 11:30 test
果然有限制到了
范例二:限制 pro1 这个用户组,每次仅能有一个用户登录系统 (maxlogins)
[root@www ~]# vi /etc/security/limits.conf
@pro1 hard maxlogins 1
如果要使用用户组功能的话,这个功能似乎对初始用户组才有效。
而如果你尝试多个 pro1 的登录时,第二个以后就无法登录了。
而且在 /var/log/secure 文件中还会出现如下的信息:
pam_limits(login:session): Too many logins (max 1) for pro1
这个文件挺有趣的,而且是设置完成就生效了,你不用重新启动任何服务的!但是PAM有个特殊的地方,由于它是在程序调用时才予以设置的,因此你修改完成的数据对于已登录系统中的用户是没有效果的,要等他再次登录时才会生效。另外,上述的设置请在测试完成后立刻批注掉,否则下次这两个用户登录就会发生问题。
/var/log/secure, /var/log/messages
如果发生任何无法登录或者是产生一些你无法预期的错误时,由于PAM模块都会将数据记载在/var/log/secure当中,所以发生了问题请务必到该文件内去查询一下问题!举例来说,我们在limits.conf的介绍中的范例二,就有谈到多重登录的错误可以到/var/log/secure内查看了!这样你也就知道为何第二个pro1无法登录啦!
14.6 Linux 主机上的用户信息传递
谈了这么多的账号问题,总是该要谈一谈,那么如何针对系统上面的用户进行查询吧?想象几个状态,如果你在Linux上面操作时,刚好有其他的用户也登录主机,你想要跟他对谈,该如何是好?你想要知道某个账号的相关信息,该如何查阅?下面我们就来介绍。
14.6.1 查询用户:w, who, last, lastlog
如何查询一个用户的相关数据呢?这还不简单!我们之前就提过了id,finger等命令了,都可以让你了解到一个用户的相关信息。那么想要知道用户到底什么时候登录呢?最简单可以使用last检查。这个玩意儿我们也在第11章bash中提过了,你可以自行前往参考啊!简单得很。
早期的 Red Hat 系统的版本中,last 仅会列出当月的登录者信息,不过在我们的CentOS 5.x 版以后,last 可以列出从系统新建之后到目前为止的所有登录者信息!这是因为日志文件轮替的设置不同所致。详细的说明可以参考后续的第19章日志文件简介。
那如果你想要知道目前已登录在系统上面的用户呢?可以通过w或who来查询。如下范例所示: [root@www ~]# w
13:13:56 up 13:00, 1 user, load average: 0.08, 0.02, 0.01
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/1 192.168.1.100 11:04 0.00s 0.36s 0.00s -bash
vbird1 pts/2 192.168.1.100 13:15 0.00s 0.06s 0.02s w
第一行显示目前的时间、开机 (up) 多久,几个用户在系统上的平均负载等;
第二行只是各个项目的说明;
第三行以后,每行代表一个用户。如上所示,root 登录并取得终端机名 pts/1 之意。
[root@www ~]# who
root pts/1 2009-03-04 11:04 (192.168.1.100)
vbird1 pts/2 2009-03-04 13:15 (192.168.1.100)
另外,如果你想要知道每个账号的最近登录的时间,则可以使用 lastlog 这个命令。lastlog 会去读取/var/log/lastlog文件,结果将数据输出,如下所示:
[root@www ~]# lastlog
Username Port From Latest
root pts/1 192.168.1.100 Wed Mar 4 11:04:22 +0800 2009
bin Never logged in
….(中间省略)….
vbird1 pts/2 192.168.1.100 Wed Mar 4 13:15:56 +0800 2009
….(以下省略)….
这样就能够知道每个账号的最近登录的时间。
14.6.2 用户对谈:write, mesg, wall
那么我是否可以跟系统上面的用户谈天说地呢?当然可以。利用write这个命令即可。write可以直接将信息传给接收者。举例来说,我们的Linux目前有vbird1与root两个人在在线,我的root要跟vbird1讲话,可以这样做:
[root@www ~]# write 用户账号 [用户所在终端接口]
[root@www ~]# who
root pts/1 2009-03-04 11:04 (192.168.1.100)
vbird1 pts/2 2009-03-04 13:15 (192.168.1.100) <==有看到 vbird1 在在线
[root@www ~]# write vbird1 pts/2
Hello, there:
Please don't do anything wrong… <==这两行是 root 写的信息!
结束时,请按下 [crtl]-d 来结束输入。此时在 vbird1 的界面中会出现:
Message from root@www.vbird.tsai on pts/1 at 13:23 …
Hello, there:
Please don't do anything wrong…
EOF
奇怪,立刻会有信息响应给vbird1!不过,当时vbird1正在查资料,这些信息会立刻打断vbird1原本的工作。所以,如果vbird1这个人不想要接收任何信息,直接执行这个动作:
[vbird1@www ~]$ mesg n
[vbird1@www ~]$ mesg
is n
不过,这个mesg的功能对root传送来的信息没有抵挡的能力。所以如果是root传送信息,vbird1还是得要收下。但是如果root的mesg是n的,那么vbird1写给root的信息会变这样:
[vbird1@www ~]$ write root
write: root has messages disabled
如果想要解开的话,再次执行“mesg y”就好啦!想要知道目前的 mesg 状态,直接执行“mesg”即可!相对于write是仅针对一个用户来传信息,我们还可以对所有系统上面的用户传送信息(广播)。如何执行?用wall即可。它的语法也是很简单。
[root@www ~]# wall "I will shutdown my linux server…"
然后你就会发现所有的人都会收到这个信息呢!
14.6.3 用户邮件信箱:mail
使用wall、write毕竟要等到用户在线才能够进行,有没有其他方式来联络啊?不是说每个Linux主机上面的用户都具有一个mailbox吗?我们可否寄信给用户?当然可以,我们可以寄、收mailbox内的信件呢!一般来说,mailbox 都会放置在/var/spool/mail 里面,一个账号一个 mailbox(文件)。举例来说,我的vbird1就具有/var/spool/mail/vbird1这个mailbox。
那么我该如何寄出信件呢?就直接使用 mail 这个命令即可!这个命令的用法很简单的,直接执行“mail username@localhost -s"邮件标题"”即可!一般来说,如果是寄给本机上的用户,基本上,连“@localhost”都不用写。举例来说,我以root寄信给vbird1,信件标题是“nice to meet you”,则:
[root@www ~]# mail vbird1 -s "nice to meet you"
Hello, D.M. Tsai
Nice to meet you in the network.
You are so nice. byebye!
. <==这里很重要,结束时,最后一行输入小数点 . 即可!
Cc: <==这里是所谓的“副本”,不需要寄给其他人,所以直接 [Enter]
[root@www ~]# <==出现提示符,表示输入完毕了!
如此一来,你就已经寄出一封信给 vbird1 这位用户,而且,该信件标题为:nice to meet you,信件内容就如同上面提到的。不过,你或许会觉得mail这个程序不好用。因为在信件编写的过程中,如果写错字而按下[Enter]进入次行,前一行的数据很难删除。那怎么办?没关系,我们使用数据流重定向。利用那个小于的符号(<)就可以达到替代键盘输入的要求了。也就是说,你可以先用vi将信件内容编好,然后再以 mail vbird1 -s "nice to meet you" < filename 来将文件内容传输即可。
请将你的主文件夹下的环境变量文件(~/.bashrc)寄给自己!
答:mail-s"bashrc file content" vbird < ~/.bashrc
刚才上面提到的是关于“寄信”的问题,那么如果是要收信呢?同样使用mail。假设我以vbird1的身份登录主机,然后输入mail后,会得到什么?
[vbird1@www ~]$ mail
Mail version 8.1 6/6/93. Type ? for help.
"/var/spool/mail/vbird1": 1 message 1 new
>N 1 root@www.vbird.tsai Wed Mar 4 13:36 18/663 "nice to meet you"
& <==这里可以输入很多的命令,如果要查阅,输入 ? 即可!
在mail当中的提示符是&符号,别搞错了,输入mail之后,我可以看到我有一封信件,这封信件的前面那个>代表目前处理的信件,而在大于符号的左边那个N代表该封信件尚未读过,如果我想要知道这个mail内部的命令有哪些,可以在&之后输入“?”,就可以看到如下的界面:
& ?
Mail Commands
t <message list> type messages
n goto and type next message
e <message list> edit messages
f <message list> give head lines of messages
d <message list> delete messages
s <message list> file append messages to file
u <message list> undelete messages
R <message list> reply to message senders
r <message list> reply to message senders and all recipients
pre <message list> make messages go back to /usr/spool/mail
m <user list> mail to specific users
q quit, saving unresolved messages in mbox
x quit, do not remove system mailbox
h print out active message headers
! shell escape
cd [directory] chdir to directory or home if none given
<message list>指的是每封邮件的左边那个数字。而几个比较常见的命令如表 14-3 所示。
表14-3
由于读过的信件若使用“q”来离开 mail 时,会将该信件移动到~/mbox 中,所以你可以想象/var/spool/mail/vbird1 为 vbird1 的“信箱”,而/home/vbird1/mbox 则为“收信箱”的意思。那如何读取/home/vbird1/mbox呢?就使用“mail-f/home/vbird1/mbox”即可。
14.7 手动新增用户
一般来说,我们不很建议大家使用手动的方式来新增用户,为什么呢?因为用户的新建涉及GID/UID 等权限的关系,而且,与文件/目录的权限也有关系,使用 useradd 可以帮我们自动设置好UID/GID主文件夹以及主文件夹相关的权限设置,但是,手动增加的时候,有可能会忘东忘西,结果导致一些困扰的发生。
不过,要了解整个系统,最好还是手动来修改比较好,至少我们的账号问题可以完全依照自己的意思去修,而不必迁就于系统的默认值。但是,还是要告诫一下朋友们,要手动设置账号时,你必须要真的很了解自己在做什么,尤其是与权限有关的设置方面。下面就让我们来玩一玩!
14.7.1 一些检查工具
既然要手动修改账号的相关配置文件,那么一些检查用户组、账号相关的命令就不可不知道啊!尤其是那个密码转换的pwconv及pwuconv可重要得很呢!下面我们稍微介绍一下这些命令吧!
pwck
pwck这个命令检查/etc/passwd这个账号配置文件内的信息,与实际的主文件夹是否存在等信息,还可以比较/etc/passwd /etc/shadow 的信息是否一致,另外,如果/etc/passwd 内的数据字段错误时,会提示用户修改。一般来说,我只是利用这个玩意儿来检查我的输入是否正确就是了。
[root@www ~]# pwck
user adm: directory /var/adm does not exist
user uucp: directory /var/spool/uucp does not exist
user gopher: directory /var/gopher does not exist
上面仅是告知我,这些账号并没有主文件夹,由于那些账号绝大部分都是系统账号,确实也不需要主文件夹的,所以,那是“正常的错误”!不理它。相应地,用户组检查可以使用grpck这个命令。
pwconv
这个命令主要的目的是将/etc/passwd内的账号与密码移动到/etc/shadow当中!早期的UNIX系统当中并没有/etc/shadow,所以,用户的登录密码早期是在/etc/passwd 的第二列,后来为了系统安全,才将密码数据移动到/etc/shadow内的。使用pwconv后,可以:
比较/etc/passwd及/etc/shadow,若/etc/passwd内存在的账号并没有对应的/etc/shadow密码时,则pwconv会去/etc/login.defs取用相关的密码数据,并新建该账号的/etc/shadow数据;
若/etc/passwd内存在加密后的密码数据时,则pwconv会将该密码列移动到/etc/shadow内,并将原本的/etc/passwd内相对应的密码列变成x!
一般来说,如果你正常使用useradd增加用户时,使用pwconv并不会有任何的操作,因为/etc/passwd与/etc/shadow并不会有上述两点问题。不过,如果手动设置账号,这个pwconv就很重要了。
pwunconv
相对于 pwconv,pwunconv 则是将/etc/shadow 内的密码列数据写回/etc/passwd 中,并且删除/etc/shadow文件。这个命令说实在的,最好不要使用,因为它会将你的/etc/shadow删除。如果你忘记备份,又不会使用pwconv的话,后果很严重呢!
chpasswd
chpasswd是个挺有趣的命令,它可以读入未加密前的密码,并且经过加密后,将加密后的密码写入/etc/shadow当中。这个命令很常被使用在批量新建账号的情况中。它可以由Standard input 读入数据,每条数据的格式是“username:password”。举例来说,我的系统当中有个用户账号为dmtsai,我想要更新他的密码(update),假如他的密码是abcdefg的话,那么我可以这样做:
[root@www ~]# echo "dmtsai:abcdefg" | chpasswd –m
神奇吧!这样就可以更新了呢!在默认的情况中,chpasswd使用的是DES加密方法来加密,我们可以使用 chpasswd -m 来使用 CentOS 5.x 默认的 MD5 加密方法。这个命令虽然已经很好用了,不过 CentOS 5.x 其实已经提供了“passwd —stdin”的参数,老实说,这个chpasswd可以不必使用了。但考虑其他版本不见得会提供—stdin给passwd这个命令,所以你还是得要了解一下这个命令的用法。
14.7.2 特殊账号(如纯数字账号)的手工新建
在我们了解了UID/GID与账号的关系之后,基本上,你应该了解了,为啥我们不建议使用纯数字的账号了。因为很多时候,系统会搞不清楚那组数字是“账号”还是“UID”,这不是很好,也因此,在早期某些版本下面,是没有办法使用数字来新建账号的。例如在 RedHat 9 的环境中,使用“useradd 1234”会显示“useradd: invalid user name'1234' ”。
在较新的distribution当中,纯数字的账号已经可以被useradd新建了。不过鸟哥还是非常不建议使用纯数字账号。例如在 setfacl 的设置值中,若使用“setfacl-mu:501:rwx filename”,那个501代表的是UID还是账号?因为setfacl的设置是支持使用UID或账号的,纯数字账号很容易造成系统的误解!
不过,有的时候,长官的命令难为啊!有时还是得要新建这方面的账号的,那该如何是好?当然可以手动来新建这样的账号。不过,为了系统安全起见,鸟哥还是不建议使用纯数字的账号。因此,下面的范例当中,我们使用手动的方式来新建一个名为 normaluser 的账号,而且这个账号属于normalgroup 这个用户组。那么整个步骤该如何是好呢?由前面的说明来看,你应该了解了账号与用户组是与/etc/group、/etc/shadow、/etc/passwd、/etc/gshadow有关,因此,整个操作是这样的:
1.先新建所需要的用户组(vi/etc/group);
2.将/etc/group与/etc/gshadow同步(grpconv);
3.新建账号的各个属性(vi /etc/passwd);
4.将/etc/passwd与/etc/shadow同步(pwconv);
5.新建该账号的密码(passwd accountname);
6.新建用户主文件夹(cp -a/etc/skel /home/accountname);
7.更改用户主文件夹的属性(chown-R accountname.group/home/accountname)。
够简单的了吧!让我们来练习下。
- 新建用户组 normalgroup ,假设 520 这个 GID 没有被使用,并且同步 gshadow
[root@www ~]# vi /etc/group
在最后一行加入下面这一行!
normalgroup:x:520:
[root@www ~]# grpconv
[root@www ~]# grep 'normalgroup' /etc/group /etc/gshadow
/etc/group:normalgroup:x:520:
/etc/gshadow:normalgroup:x::
最后确定 /etc/group、/etc/gshadow 都存在这个用户组才行
- 新建 normaluser 这个账号,假设 UID 700 没被使用。
[root@www ~]# vi /etc/passwd
在最后一行加入下面这一行!
normaluser:x:700:520::/home/normaluser:/bin/bash
- 同步密码,并且新建该用户的密码
[root@www ~]# pwconv
[root@www ~]# grep 'normaluser' /etc/passwd /etc/shadow
/etc/passwd:normaluser:x:700:520::/home/normaluser:/bin/bash
/etc/shadow:normaluser:x:14307:0:99999:7:::
确定 /etc/passwd、/etc/shadow 都含有 normaluser 的信息了!但是密码还不对~
[root@www ~]# passwd normaluser
Changing password for user normaluser.
New UNIX password:
Retype new UNIX password:
passwd: all authentication tokens updated successfully.
- 新建用户主文件夹,并且修改权限!
[root@www ~]# cp -a /etc/skel /home/normaluser
[root@www ~]# chown -R normaluser:normalgroup /home/normaluser
[root@www ~]# chmod 700 /home/normaluser
别怀疑!这样就搞定了一个账号的设置了。从此以后,你可以新建任何名称的账号。不过,还是不建议你设置一些奇怪的账号名称。
14.7.3 批量新建账号模板(适用于passwd —stdin参数)
由于CentOS 5.x的passwd已经提供了—stdin的功能,因此如果我们可以提供账号密码的话,那么就能够很简单地新建起我们的账号密码了。下面鸟哥制作一个简单的script来执行新增用户的功能。
[root@www ~]# vi account1.sh
!/bin/bash
这个程序用来新建账号,功能有:
1. 检查 account1.txt 是否存在,并将该文件内的账号取出;
2. 新建上述文件的账号;
3. 将上述账号的密码修改成为强制第一次进入需要修改密码的格式。
2009/03/04 VBird
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
检查 account1.txt 是否存在
if [ ! -f account1.txt ]; then
echo "所需要的账号文件不存在,请新建 account1.txt ,每行一个账号名称"
exit 1
fi
usernames=$(cat account1.txt)
for username in $usernames
do
useradd $username <==新增账号
echo $username | passwd —stdin $username <==与账号相同的密码
chage -d 0 $username <==强制登录修改密码
done
接下来只要新建 account1.txt 这个文件即可。鸟哥新建这个文件里面共有 10 行,你可以自行新建该文件。内容每一行一个账号。注意,最终的结果会是每个账号具有与账号相同的密码,且初次登录后,必须要重新设置密码后才能够再次登录使用系统资源!
[root@www ~]# vi account1.txt
std01
std02
std03
std04
std05
std06
std07
std08
std09
std10
[root@www ~]# sh account1.sh
Changing password for user std01.
passwd: all authentication tokens updated successfully.
….(后面省略)….
这个简单的脚本你可以按如下的链接下载:
http://linux.vbird.org/linux_basic/0410accountmanager/account1.sh
另外,鸟哥的script是在zh_CN.big5的语系下新建的,如果你需要转成utf8的编码格式,请下载上述文件后,利用第10章谈到的iconv来处理语系的问题!
14.7.4 批量新建账号的范例(适用于连续数字,如学号)
前一小节的内容已经可以满足很多朋友的账号构建方法了,不过,某些时候上述的script还是很麻烦,因为需要手动编辑 account1.txt。如果是类似学校这种学号非常类似的账号时,有没有更快的方案?此外,如果需要每个班级同属于一个用户组,不同班级的用户组不同,又该如何构建?这是比较麻烦的。
目前很多网站都有提供大量新建账号的工具,例如卧龙小三大师提供的好用的cmpwd程序:
http://news.ols3.net/techdoc/old/howtouse_cmpwd101.htm
但是小三大师的程序仅供学术单位使用,一般个人是无权使用的(参考上述链接的授权)。不过,其实我们也可以利用简单的script来帮我们实现。例如下面这个程序,它的执行结果与小三大师提供的程序差不多。但是因为我是直接以useradd来新增的,所以,即使不了解UID,也是可以适用的,整个程序的特色是:
默认不允许使用纯数字方式新建账号;
可加入年级来区分账号;
可设置账号的起始号码与账号数量;
有两种密码新建方式,可以与账号相同或程序自行以随机数新建密码文件。
执行方法也简单,请自行参考,不再多说。使用时请注意,不要在单位使用的主机上面进行测试,因为这个程序会大量新建账号。
!/bin/bash
#
这个程序主要帮你新建大量的账号之用,更多的使用方法请参考:
http://linux.vbird.org/linux_basic/0410accountmanager.php#manual_amount
#
本程序为鸟哥自行开发,在 CentOS 5.x 上使用没有问题,
但不保证绝不会发生错误!使用时,请自行负担风险~
#
History:
2005/09/05 VBird 刚才才写完,使用看看先~
2009/03/04 VBird 加入一些语系的修改与说明,修改密码产生方式 (用 openssl)
export LANG=zh_TW.big5
export PATH=/sbin:/usr/sbin:/bin:/usr/bin
accountfile="user.passwd"
1. 进行账号相关的输入先!
echo ""
echo "例如我们学校学生的学号为: 4960c001 到 4960c060 ,那么:"
echo "账号开头代码为 :4"
echo "账号层级或年级为 :960c"
echo "号码数字位数为(001~060):3"
echo "账号开始号码为 :1"
echo "账号数量为 :60"
echo ""
read -p "账号开头代码 ( Input title name, ex> std )======> " username_start
read -p "账号层级或年级 ( Input degree, ex> 1 or enter )=> " username_degree
read -p "号码部分的数字位数 ( Input # of digital )======> " nu_nu
read -p "起始号码 ( Input start number, ex> 520 )========> " nu_start
read -p "账号数量 ( Input amount of users, ex> 100 )=====> " nu_amount
read -p "密码标准 1) 与账号相同 2)随机数自定义 ==============> " pwm
if [ "$username_start" == "" ]; then
echo "没有输入开头的代码,不给你执行!" ; exit 1
fi
判断数字系统
testing0=$(echo $nu_nu | grep '[^0-9]' )
testing1=$(echo $nu_amount | grep '[^0-9]' )
testing2=$(echo $nu_start | grep '[^0-9]' )
if [ "$testing0" != "" -o "$testing1" != "" -o "$testing2" != "" ]; then
echo "输入的号码不对,有非数字的内容!" ; exit 1
fi
if [ "$pwm" != "1" ]; then
pwm="2"
fi
2. 开始输出账号与密码文件!
[ -f "$accountfile" ] && mv $accountfile "$accountfile"$(date +%Y%m%d)
nu_end=$(($nu_start+$nu_amount-1))
for (( i=$nu_start; i<=$nu_end; i++ ))
do
nu_len=${#i}
if [ $nu_nu -lt $nu_len ]; then
echo "数值的位数($i->$nu_len)已经比你设置的位数($nu_nu)还大!"
echo "程序无法继续"
exit 1
fi
nu_diff=$(( $nu_nu - $nu_len ))
if [ "$nu_diff" != "0" ]; then
nu_nn=0000000000
nu_nn=${nu_nn:1:$nu_diff}
fi
account=${username_start}${username_degree}${nu_nn}${i}
if [ "$pwm" == "1" ]; then
password="$account"
else
password=$(openssl rand -base64 6)
fi
echo "$account":"$password" | tee -a "$accountfile"
done
3. 开始新建账号与密码!
cat "$accountfile" | cut -d':' -f1 | xargs -n 1 useradd -m
chpasswd < "$accountfile"
pwconv
echo "OK!新建完成!"
如果有需要新建同一班级具有同一组的话,可以先使用 groupadd 新建组后,将该组加入“cat"$accountfile" | cut -d':' -f1 | xargs-n 1 useradd -m -g groupname ”那行!这个脚本可以在下面的链接下载:
http://linux.vbird.org/linux_basic/0410accountmanager/account2.sh
如果仅是测试而已,想要将刚才新建的用户整个删除,则可以使用如下的脚本来进行删除!
[root@www ~]# vi delaccount2.sh
!/bin/bash
usernames=$(cat user.passwd | cut -d ':' -f 1)
for username in $usernames
do
echo "userdel -r $username"
userdel -r $username
done
[root@www ~]# sh delaccount2.sh
总之,账号管理是很重要的。希望上面的说明能够对大家有点帮助。
14.8 重点回顾
Linux操作系统上面,关于账号与用户组,其实记录的是UID/GID的数字而已。
用户账号/用户组与UID/GID的对应,参考/etc/passwd及/etc/group两个文件。
/etc/passwd文件结构以冒号隔开,共分为七个字段,分别是账号名称、密码、UID、GID、全名、主文件夹、shell。
UID只有0与非0两种,非0则为一般账号。一般账号又分为系统账号(1~499)及可登录者账号(大于500)。
账号的密码已经移动到/etc/shadow文件中,该文件权限为仅有root可以改动。该文件分为九个字段,内容为账号名称、加密密码、密码更动日期、密码最小可变动日期、密码最大需变动日期、密码过期前警告天数、密码失效天数、账号失效日、保留未使用。
用户可以支持多个用户组,其中在新建文件时会影响新文件用户组者,为有效用户组。而写入/etc/passwd的第四个字段者,称为初始用户组。
与用户新建、更改参数、删除有关的命令为 useradd,usermod, userdel 等,密码新建则为 passwd。
与用户组新建、修改、删除有关的命令为 groupadd, groupmod, groupdel 等。
用户组的查看与有效用户组的切换分别为groups及newgrp命令。
useradd 命令作用参考的文件有/etc/default/useradd,/etc/login.defs, /etc/skel/等。
查看用户详细的密码参数,可以使用“chage-l账号”来处理。
用户自行修改参数的命令有chsh,chfn等,查看命令则有d,finger等。
ACL可进行单一个人或组的权限管理,但ACL的启动需要有文件系统的支持。
ACL的设置可使用setfacl,查阅则使用getfacl。
身份切换可使用su,也可使用sudo,但使用sudo者,必须先以visudo设置可使用的命令。
PAM 模块可进行某些程序的验证程序,与 PAM 模块有关的配置文件位于/etc/pam.d/及/etc/security/中。
系统上面账号登录情况的查询,可使用 w, who, last, lastlog 等。
在线与用户交谈可使用write、wall,脱机状态下可使用mail传送邮件!
14.9 本章习题
情境模拟题
想将本服务器的账号分开管理,分为单纯邮件使用与可登录系统账号两种。其中若为纯邮件账号时,将该账号加入mail为初始用户组,且此账号不可使用bash等shell登录系统;若为可登录账号时,将该账号加入youcan这个次要用户组。
目标:了解/sbin/nologin的用途;
前提:可自行查看用户是否已经新建等问题;
需求:需已了解useradd、groupadd等命令的用法。
解决方案如下:
1.预先查看一下两个用户组是否存在。
[root@www ~]# grep mail /etc/group
[root@www ~]# grep youcan /etc/group
[root@www ~]# groupadd youcan
可发现youcan尚未被新建,因此如上所示,我们主动去新建这个用户组。
2.开始新建三个邮件账号,此账号名称为 pop1, pop2, pop3,且密码与账号相同。可使用如下的程序来处理:
[root@www ~]# vim popuser.sh
!/bin/bash
for username in pop1 pop2 pop3
do
useradd -g mail -s /sbin/nologin -M $username
echo $username | passwd —stdin $username
done
[root@www ~]# sh popuser.sh
3.开始新建一般账号,只是这些一般账号必须要能够登录,并且需要使用次要用户组的支持!所以:
[root@www ~]# vim loginuser.sh
!/bin/bash
for username in youlog1 youlog2 youlog3
do
useradd -G youcan -s -m $username
echo $username | passwd —stdin $username
done
[root@www ~]# sh loginuser.sh
4.这样就将账号分开管理了!非常简单吧!
简答题部分
root的UID与GID是多少?而基于这个理由,我要让test这个账号具有root的权限,应该怎么做?
假设我是一个系统管理员,我有一个用户最近不乖顺,所以我想暂时将他的账号停掉,让他近期无法进行任何操作,等到将来他乖顺一点之后,我再将他的账号启用,请问我可以怎么做比较好?
我在使用useradd的时候,新增的账号里面的UID、GID还有其他相关的密码控制,都是在哪几个文件里面设置的?
我希望我在设置每个账号的时候(使用useradd),默认情况中,他们的主文件夹就含有一个名称为www的子目录,我应该怎么做比较好?
简单说明系统账号与一般用户账号的区别。
简单说明,为何 CentOS5.x 新建用户时,它会主动帮用户新建一个用户组,而不是使用/etc/default/useradd的设置?
新建一个用户名称 alex,他所属用户组为 alexgroup,预计使用 csh,他的全名为"Alex Tsai",且他还得要加入users用户组当中。
由于种种因素,导致你的用户主文件夹以后都需要被放置到/account这个目录下。请问,我该如何做才可以当使用useradd时默认的主文件夹就指向/account?
我想要让 dmtsai 这个用户加入 vbird1, vbird2, vbird3 这三个用户组,且不影响 dmtsai 原本已经支持的次要用户组时,该如何操作?