在 Linux 系统下管理用户的身份与帐号!
要登录 Linux 系统一定要有帐号与密码才行,否则怎么登录,您说是吧?不过, 不同的用户应该要拥有不同的权限才行吧?我们还可以通过 user/group 的特殊权限设置, 来规范出不同的群组开发项目呢~在 Linux 的环境下,我们可以通过很多方式来限制用户能够使用的系统资源, 包括 十一章、bash 提到的 ulimit 限制、还有特殊权限限制,如 umask 等等。 通过这些举动,我们可以规范出不同用户的使用资源。另外,还记得系统管理员的帐号吗?对! 就是 root 。请问一下,除了 root 之外,是否可以有其他的系统管理员帐号? 为什么大家都要尽量避免使用数字型态的帐号?如何修改用户相关的信息呢?这些我们都得要了解了解的!
管理员的工作中,相当重要的一环就是『管理帐号』啦!因为整个系统都是你在管理的, 并且所有一般用户的帐号申请,都必须要通过你的协助才行!所以你就必须要了解一下如何管理好一个服务器主机的帐号啦! 在管理 Linux 主机的帐号时,我们必须先来了解一下 Linux 到底是如何辨别每一个用户的!
虽然我们登录 Linux 主机的时候,输入的是我们的帐号,但是其实 Linux 主机并不会直接认识你的『帐号名称』的,他仅认识 ID 啊 (ID 就是一组号码啦)。 由于电脑仅认识 0 与 1,所以主机对于数字比较有概念的;至于帐号只是为了让人们容易记忆而已。 而你的 ID 与帐号的对应就在 /etc/passwd 当中哩。
那么到底有几种 ID 呢?还记得我们在第六章内有提到过, 每一个文件都具有『拥有人与拥有群组』的属性吗?没错啦~每个登录的用户至少都会取得两个 ID ,一个是用户 ID (User ID ,简称 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 里面,将数字改回来喔!
Linux 系统上面的用户如果需要登录主机以取得 shell 的环境来工作时,他需要如何进行呢? 首先,他必须要在电脑前面利用 tty1~tty7 的终端机提供的 login 接口,并输入帐号与密码后才能够登录。 如果是通过网络的话,那至少用户就得要学习 ssh 这个功能了 (服务器篇再来谈)。 那么你输入帐号密码后,系统帮你处理了什么呢?
大致上的情况就像这样,所以当你要登录你的 Linux 主机的时候,那个 /etc/passwd 与 /etc/shadow 就必须要让系统读取啦 (这也是很多攻击者会将特殊帐号写到 /etc/passwd 里头去的缘故),所以呢,如果你要备份 Linux 的系统的帐号的话,那么这两个文件就一定需要备份才行呦!
由上面的流程我们也知道,跟用户帐号有关的有两个非常重要的文件,一个是管理用户 UID/GID 重要参数的 /etc/passwd ,一个则是专门管理密码相关数据的 /etc/shadow 啰!那这两个文件的内容就非常值得进行研究啦! 底下我们会简单的介绍这两个文件,详细的说明可以参考 man 5 passwd 及 man 5 shadow (注1)。
这个文件的构造是这样的:每一行都代表一个帐号,有几行就代表有几个帐号在你的系统中! 不过需要特别留意的是,里头很多帐号本来就是系统正常运作所必须要的,我们可以简称他为系统帐号, 例如 bin, daemon, adm, nobody 等等,这些帐号请不要随意的杀掉他呢! 这个文件的内容有点像这样:
[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 这个系统管理员那一行好了, 你可以明显的看出来,每一行使用『:』分隔开,共有七个咚咚,分别是:
id 范围 | 该 ID 用户特性 |
0 (系统管理员) | 当 UID 是 0 时,代表这个帐号是『系统管理员』! 所以当你要让其他的帐号名称也具有 root 的权限时,将该帐号的 UID 改为 0 即可。 这也就是说,一部系统上面的系统管理员不见得只有 root 喔! 不过,很不建议有多个帐号的 UID 是 0 啦~ |
1~499 (系统帐号) | 保留给系统使用的 ID,其实除了 0 之外,其他的 UID 权限与特性并没有不一样。缺省 500
以下的数字让给系统作为保留帐号只是一个习惯。 由于系统上面启动的服务希望使用较小的权限去运作,因此不希望使用 root 的身份去运行这些服务, 所以我们就得要提供这些运作中程序的拥有者帐号才行。这些系统帐号通常是不可登录的, 所以才会有我们在第十一章提到的 /sbin/nologin 这个特殊的 shell 存在。 根据系统帐号的由来,通常系统帐号又约略被区分为两种: 1~99:由 distributions 自行创建的系统帐号; 100~499:若用户有系统帐号需求时,可以使用的帐号 UID。 |
500~65535 (可登录帐号) | 给一般用户用的。事实上,目前的 linux 内核 (2.6.x 版)已经可以支持到 4294967295 (2^32-1) 这么大的 UID 号码喔! |
我们知道很多程序的运作都与权限有关,而权限与 UID/GID 有关!因此各程序当然需要读取 /etc/passwd 来了解不同帐号的权限。 因此 /etc/passwd 的权限需设置为 -rw-r--r-- 这样的情况, 虽然早期的密码也有加密过,但却放置到 /etc/passwd 的第二个字段上!这样一来很容易被有心人士所窃取的, 加密过的密码也能够通过暴力破解法去 trial 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 同样以『:』作为分隔符号,如果数一数,会发现共有九个字段啊,这九个字段的用途是这样的:
[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 当天。举个例子来说好了,假如我的 dmtsai 这个用户的密码栏如下所示:
dmtsai:$1$vyUuj.eX$omt6lKJvMcIZHx4H7RI1V.:14299:5:60:7:5:14419:
这表示什么呢?先要注意的是 14299 是 2009/02/24 。所以 dmtsai 这个用户的密码相关意义是:
You must wait longer to change your password passwd: Authentication token manipulation error画面中告诉我们:你必须要等待更久的时间才能够变更密码之意啦!
Warning: your password will expire in 5 days
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
通过这样的说明,您应该会比较容易理解了吧?由于 shadow 有这样的重要性,因此可不能随意修改喔! 但在某些情况底下你得要使用各种方法来处理这个文件的!举例来说,常常听到人家说:『我的密码忘记了』, 或者是『我的密码不晓得被谁改过,跟原先的不一样了』,这个时候怎么办?
认识了帐号相关的两个文件 /etc/passwd 与 /etc/shadow 之后,你或许还是会觉得奇怪, 那么群组的设置档在哪里?还有,在 /etc/passwd 的第四栏不是所谓的 GID 吗?那又是啥? 呵呵~此时就需要了解 /etc/group 与 /etc/gshadow 啰~
这个文件就是在记录 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
这个文件每一行代表一个群组,也是以冒号『:』作为字段的分隔符号,共分为四栏,每一字段的意义是:
谈完了 /etc/passwd, /etc/shadow, /etc/group 之后,我们可以使用一个简单的图标来了解一下 UID / GID 与密码之间的关系, 图标如下。其实重点是 /etc/passwd 啦,其他相关的数据都是根据这个文件的字段去找寻出来的。 下图中, root 的 UID 是 0 ,而 GID 也是 0 ,去找 /etc/group 可以知道 GID 为 0 时的群组名称就是 root 哩。 至于密码的寻找中,会找到 /etc/shadow 与 /etc/passwd 内同帐号名称的那一行,就是密码相关数据啰。
至于在 /etc/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)。
如果我以 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 是有限制的,那就是你想要切换的群组必须是你已经有支持的群组。举例来说, 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 就是了。如果以图标来看就是如下所示:
虽然用户的环境设置(例如环境变量等等其他数据)不会有影响,但是用户的『群组权限』将会重新被计算。 但是需要注意,由于是新取得一个 shell ,因此如果你想要回到原本的环境中,请输入 exit 回到原本的 shell 喔!
既然如此,也就是说,只要我的用户有支持的群组就是能够切换成为有效群组!好了, 那么如何让一个帐号加入不同的群组就是问题的所在啰。你要加入一个群组有两个方式,一个是通过系统管理员 (root) 利用 usermod 帮你加入,如果 root 太忙了而且你的系统有设置群组管理员,那么你可以通过群组管理员以 gpasswd 帮你加入他所管理的群组中!详细的作法留待下一小节再来介绍啰!
刚刚讲了很多关于『有效群组』的概念,另外,也提到 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 一模一样啊!是这样没错~不过,要注意的大概就是第二个字段吧~第二个字段是密码栏, 如果密码栏上面是『!』时,表示该群组不具有群组管理员!至于第四个字段也就是支持的帐号名称啰~ 这四个字段的意义为:
以系统管理员的角度来说,这个 gshadow 最大的功能就是创建群组管理员啦! 那么什么是群组管理员呢?由于系统上面的帐号可能会很多,但是我们 root 可能平时太忙碌,所以当有用户想要加入某些群组时, root 或许会没有空管理。此时如果能够创建群组管理员的话,那么该群组管理员就能够将那个帐号加入自己管理的群组中! 可以免去 root 的忙碌啦!不过,由于目前有类似 sudo 之类的工具, 所以这个群组管理员的功能已经很少使用了。我们会在后续的 gpasswd 中介绍这个实作。
好啦!既然要管理帐号,当然是由添加与移除用户开始的啰~底下我们就分别来谈一谈如何添加、 移除与更改用户的相关信息吧~
要如何在 Linux 的系统添加一个用户啊?呵呵~真是太简单了~我们登录系统时会输入 (1)帐号与 (2)密码, 所以创建一个可用的帐号同样的也需要这两个数据。那帐号可以使用 useradd 来新建用户,密码的给予则使用 passwd 这个指令!这两个指令下达方法如下:
[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/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 创建用户帐号时,其实会更改不少地方,至少我们就知道底下几个文件:
那请教一下,你有没有想过,为何『 useradd vbird1 』会主动在 /home/vbird1 创建起用户的家目录?家目录内有什么数据且来自哪里?为何缺省使用的是 /bin/bash 这个 shell ?为何密码字段已经都规范好了 (0:99999:7 那一串)?呵呵!这就得要说明一下 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 去观察该文件的内容。搭配上头刚刚谈过的范例一的运作结果,上面这些设置项目所造成的行为分别是:
除了这些基本的帐号设置值之外, 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 的加密机制处理
这个文件规范的数据则是如下所示:
现在你知道啦,使用 useradd 这支程序在创建 Linux 上的帐号时,至少会参考:
这些文件,不过,最重要的其实是创建 /etc/passwd, /etc/shadow, /etc/group, /etc/gshadow 还有用户家目录就是了~所以,如果你了解整个系统运作的状态,也是可以手动直接修改这几个文件就是了。 OK!帐号创建了,接下来处理一下用户的密码吧!
刚刚我们讲到了,使用 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 』这个关键字时才是修改密码成功喔!
为何用户要设订自己的密码会这么麻烦啊?这是因为密码的安全性啦!如果密码设置太简单, 一些有心人士就能够很简单的猜到你的密码,如此一来人家就可能使用你的一般帐号登录你的主机或使用其他主机资源, 对主机的维护会造成困扰的!所以新的 distributions 是使用较严格的 PAM 模块来管理密码,这个管理的机制写在 /etc/pam.d/passwd 当中。而该文件与密码有关的测试模块就是使用:pam_cracklib.so,这个模块会检验密码相关的信息, 并且取代 /etc/login.defs 内的 PASS_MIN_LEN 的设置啦!关于 PAM 我们在本章后面继续介绍,这里先谈一下, 理论上,你的密码最好符合如下要求:
为了方便系统管理,新版的 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:: # 密码字段恢复正常!
是否很有趣啊!您可以自行管理一下你的帐号的密码相关参数喔!接下来让我们用更简单的方法来查阅密码参数喔!
除了使用 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 这个帐号在第一次登录时可以使用与帐号同名的密码登录, 但登录时就会被要求立刻更改密码,更改密码完成后就会被踢出系统。再次登录时就能够使用新密码登录了! 这个功能对学校老师非常有帮助!因为我们不想要知道学生的密码,那么在初次上课时就使用与学号相同的帐号/密码给学生, 让她们登录时自行设置她们的密码,如此一来就能够避免其他同学随意使用别人的帐号,也能够保证学生知道如何更改自己的密码!
所谓这『人有失手,马有乱蹄』,您说是吧?所以啰,当然有的时候会『不小心』在 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 ,是因为我们仅要修改目录的权限而非内部文件的权限!
这个功能就太简单了,目的在删除用户的相关数据,而用户的数据有:
整个指令的语法非常简单:
[root@www ~]# userdel [-r] username 选项与参数: -r :连同用户的家目录也一起删除 范例一:删除 vbird2 ,连同家目录一起删除 [root@www ~]# userdel -r vbird2
这个指令下达的时候要小心了!通常我们要移除一个帐号的时候,你可以手动的将 /etc/passwd 与 /etc/shadow 里头的该帐号取消即可!一般而言,如果该帐号只是『暂时不激活』的话,那么将 /etc/shadow 里头帐号失效日期 (第八字段) 设置为 0 就可以让该帐号无法使用,但是所有跟该帐号相关的数据都会留下来! 使用 userdel 的时机通常是『你真的确定不要让该用户在主机上面使用任何数据了!』
另外,其实用户如果在系统上面操作过一阵子了,那么该用户其实在系统内可能会含有其他文件的。 举例来说,他的邮件信箱 (mailbox) 或者是例行性工作调度 (crontab, 十六章) 之类的文件。 所以,如果想要完整的将某个帐号完整的移除,最好可以在下达 userdel -r username 之前, 先以『 find / -user username 』查出整个系统内属于 username 的文件,然后再加以删除吧!
不论是 useradd/usermod/userdel ,那都是系统管理员所能够使用的指令, 如果我是一般身份用户,那么我是否除了密码之外,就无法更改其他的数据呢? 当然不是啦!这里我们介绍几个一般身份用户常用的帐号数据变更与查找指令啰!
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 文件里面的东西。列出的信息说明如下:
不过是否能够查阅到 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 有点像是: 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 里头更改你『个人属性』的那一个数据啦!不过还是可以自己玩一玩!尤其是用来提醒自己相关数据啦! ^_^
这就是 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 这个指令则可以查找某人或自己的相关 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 这个指令也可以用来判断系统上面有无某帐号!
OK!了解了帐号的添加、删除、更动与查找后,再来我们可以聊一聊群组的相关内容了。 基本上,群组的内容都与这两个文件有关:/etc/group, /etc/gshadow。 群组的内容其实很简单,都是上面两个文件的添加、修改与移除而已, 不过,如果再加上有效群组的概念,那么 newgrp 与 gpasswd 则不可不知呢!
[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 群组名』的方式来创建啦! 不过,这见仁见智啦!看你自己的抉择啰!
跟 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 自然就是在删除群组的啰~用法很简单:
[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) 的 initial group 使用该群组!』 如果查阅一下,你会发现在 /etc/passwd 内的 vbird1 第四栏的 GID 就是 /etc/group 内的 vbird1 那个群组的 GID ,所以啰,当然无法删除~否则 vbird1 这个用户登录系统后, 就会找不到 GID ,那可是会造成很大的困扰的!那么如果硬要删除 vbird1 这个群组呢? 你『必须要确认 /etc/passwd 内的帐号没有任何人使用该群组作为 initial group 』才行喔!所以,你可以:
如果系统管理员太忙碌了,导致某些帐号想要加入某个项目时找不到人帮忙!这个时候可以创建『群组管理员』喔! 什么是群组管理员呢?就是让某个群组具有一个管理员,这个群组管理员可以管理哪些帐号可以加入/移出该群组! 那要如何『创建一个群组管理员』呢?就得要通过 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 啰~
帐号管理不是随意建置几个帐号就算了!有时候我们需要考量到一部主机上面可能有多个帐号在协同工作! 举例来说,在大学任教时,我们学校的专题生是需要分组的,这些同一组的同学间必须要能够互相修改对方的数据文件, 但是同时这些同学又需要保留自己的私密数据,因此直接公开家目录是不适宜的。那该如何是好? 为此,我们底下提供几个例子来让大家思考看看啰:
任务一:单纯的完成上头交代的任务,假设我们需要的帐号数据如下,你该如何实作?
帐号名称 | 帐号全名 | 支持次要群组 | 是否可登录主机 | 密码 |
myuser1 | 1st user | mygroup1 | 可以 | password |
myuser2 | 2nd user | mygroup1 | 可以 | password |
myuser3 | 3rd user | 无额外支持 | 不可以 | password |
处理的方法如下所示:
# 先处理帐号相关属性的数据: [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 呢还记得第七章谈到的 SGID 吧?为了让三个用户能够互相修改对方的文件, 这个 SGID 是必须要存在的喔!如果连这里都能够理解,嘿嘿!您的帐号管理已经有一定程度的概念啰! ^_^
但接下来有个困扰的问题发生了!假如任务一的 myuser1 是 projecta 这个项目的助理,他需要这个项目的内容, 但是他『不可以修改』项目目录内的任何数据!那该如何是好?你或许可以这样做:
真要命!传统的 Linux 权限无法针对某个个人设置专属的权限吗?其实是可以啦!接下来我们就来谈谈这个功能吧!
从第六章开始,我们就一直强调 Linux 的权限概念是非常重要的! 但是传统的权限仅有三种身份 (owner, group, others) 搭配三种权限 (r,w,x) 而已,并没有办法单纯的针对某一个用户或某一个群组来设置特定的权限需求,例如前一小节最后的那个任务! 此时就得要使用 ACL 这个机制啦!这玩意挺有趣的,底下我们就来谈一谈:
ACL 是 Access Control List 的缩写,主要的目的是在提供传统的 owner,group,others 的 read,write,execute 权限之外的细部权限设置。ACL 可以针对单一用户,单一文件或目录来进行 r,w,x 的权限规范,对于需要特殊权限的使用状况非常有帮助。
那 ACL 主要可以针对哪些方面来控制权限呢?他主要可以针对几个项目:
好了,再来看看如何让你的文件系统可以支持 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 里面的内容修改一下即可!
好了,让你的 filesystem 启动 ACL 支持后,接下来该如何设置与观察 ACL 呢? 很简单,利用这两个指令就可以了:
先让我们来瞧一瞧 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 吧!
[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 啦!然后再分别依据不同的用户/群组去规范她们的权限就是了。
例题:
将前一小节任务二中 /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 文件名 』即可啦! 太简单了!鸟哥就不另外介绍了!请自行测试测试吧!
什么?在 Linux 系统当中还要作身份的变换?这是为啥?可能有底下几个原因啦!
由于上述考量,所以我们都是使用一般帐号登录系统的,等有需要进行系统维护或软件更新时才转为 root 的身份来动作。 那如何让一般用户转变身份成为 root 呢?主要有两种方式喔:
底下我们就来说一说 su 跟 sudo 的用法啦!
su 是最简单的身份切换指令了,他可以进行任何身份的切换唷!方法如下:
[root@www ~]# su [-lm] [-c 指令] [username] 选项与参数: - :单纯使用 - 如『 su - 』代表使用 login-shell 的变量文件读取方式来登录系统; 若用户名没有加上去,则代表切换为 root 的身份。 -l :与 - 类似,但后面需要加欲切换的用户帐号!也是 login-shell 的方式。 -m :-m 与 -p 是一样的,表示『使用目前的环境设置,而不读取新用户的设置档』 -c :仅进行一次指令,所以 -c 后面可以加上指令喔!
上表的解释当中有出现之前第十一章谈过的 login-shell 设置档读取方式,如果你忘记那是啥东西, 请先回去第十一章瞧瞧再回来吧!这个 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 很方便啦,不过缺点是,当我的主机是多人共管的环境时,如果大家都要使用 su 来切换成为 root 的身份,那么不就每个人都得要知道 root 的密码,这样密码太多人知道可能会流出去, 很不妥当呢!怎办?通过 sudo 来处理即可!
相对于 su 需要了解新切换的用户密码 (常常是需要 root 的密码), sudo 的运行则仅需要自己的密码即可! 甚至可以设置不需要密码即可运行 sudo 呢!由于 sudo 可以让你以其他用户的身份运行指令 (通常是使用 root 的身份来运行指令),因此并非所有人都能够运行 sudo , 而是仅有规范到 /etc/sudoers 内的用户才能够运行 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 的身份创建 ~vbird1/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 真是他 X 的好用了!立刻以 sshd 的权限在 /tmp 底下创建文件!查阅一下文件权限你就了解意义啦! 至于范例二则更使用多重指令串 (通过分号 ; 来延续指令进行),使用 sh -c 的方法来运行一连串的指令, 如此真是好方便!
但是 sudo 缺省仅有 root 能使用啊!为什么呢?因为 sudo 的运行是这样的流程:
所以说,sudo 运行的重点是:『能否使用 sudo 必须要看 /etc/sudoers 的设置值, 而可使用 sudo 者是通过输入用户自己的密码来运行后续的指令串』喔!由于能否使用与 /etc/sudoers 有关, 所以我们当然要去编辑 sudoers 文件啦!不过,因为该文件的内容是有一定的规范的,因此直接使用 vi 去编辑是不好的。 此时,我们得要通过 visudo 去修改这个文件喔!
从上面的说明我们可以知道,除了 root 之外的其他帐号,若想要使用 sudo 运行属于 root 的权限指令,则 root 需要先使用 visudo 去修改 /etc/sudoers ,让该帐号能够使用全部或部分的 root 指令功能。为什么要使用 visudo 呢?这是因为 /etc/sudoers 是有设置语法的,如果设置错误那会造成无法使用 sudo 指令的不良后果。因此才会使用 visudo 去修改, 并在结束离开修改画面时,系统会去检验 /etc/sudoers 的语法就是了。
一般来说,visudo 的设置方式有几种简单的方法喔,底下我们以几个简单的例子来分别说明:
[root@www ~]# visudo ....(前面省略).... root ALL=(ALL) ALL <==找到这一行,大约在 76 行左右 vbird1 ALL=(ALL) ALL <==这一行是你要添加的! ....(前面省略)....有趣吧!其实 visudo 只是利用 vi 将 /etc/sudoers 文件调用出来进行修改而已,所以这个文件就是 /etc/sudoers 啦! 这个文件的设置其实很简单,如上面所示,如果你找到 76 行 (有 root 设置的那行) 左右,看到的数据就是:
用户帐号 登录者的来源主机名称=(可切换的身份) 可下达的指令
root ALL=(ALL) ALL <==这是默认值
上面这一行的四个组件意义是:[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 这个用户的『操守』才行!否则随便设置一个用户,他恶搞系统怎办?另外,一个一个设置太麻烦了, 能不能使用群组的方式来设置呢?参考底下的方式吧。
[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 啦!该关键字是免除密码输入的意思喔!
[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 的密码!很有用处的!
[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 这两行即可!设置方面会比较简单有弹性喔!
[root@www ~]# visudo User_Alias ADMINS = pro1, pro2, pro3, myuser1 ADMINS ALL=(root) /bin/su -接下来,上述的 pro1, pro2, pro3, myuser1 这四个人,只要输入『 sudo su - 』并且输入『自己的密码』后, 立刻变成 root 的身份!不但 root 密码不会外流,用户的管理也变的非常方便! 这也是实务上面多人共管一部主机时常常使用的技巧呢!这样管理确实方便,不过还是要强调一下大前提, 那就是『这些你加入的用户,全部都是你能够信任的用户』!
我们前面一直谈到的大多是一般身份用户与系统管理员 (root) 的相关操作, 而且大多是讨论关于可登录系统的帐号来说。那么换个角度想,如果我今天想要创建的, 是一个『仅能使用 mail server 相关邮件服务的帐号,而该帐号并不能登录 Linux 主机』呢?如果不能给予该帐号一个密码,那么该帐号就无法使用系统的各项资源,当然也包括 mail 的资源, 而如果给予一个密码,那么该帐号就可能可以登录 Linux 主机啊!呵呵~伤脑筋吧~ 所以,底下让我们来谈一谈这些有趣的话题啰!
另外,在本章之前谈到过 /etc/login.defs 文件中,关于密码长度应该缺省是 5 个字符串长度,但是我们上面也谈到,该设置值已经被 PAM 模块所取代了,那么 PAM 是什么?为什么他可以影响我们用户的登录呢?这里也要来谈谈的!
在本章一开头的 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 ~]#
结果会发现与原本的缺省消息不一样喔! ^_^
|
在过去,我们想要对一个用户进行认证 (authentication),得要要求用户输入帐号密码, 然后通过自行撰写的程序来判断该帐号密码是否正确。也因为如此,我们常常得使用不同的机制来判断帐号密码, 所以搞的一部主机上面拥有多个各别的认证系统,也造成帐号密码可能不同步的验证问题! 为了解决这个问题因此有了 PAM (Pluggable Authentication Modules, 嵌入式模块) 的机制!
PAM 可以说是一套应用程序接口 (Application Programming Interface, API),他提供了一连串的验证机制,只要用户将验证阶段的需求告知 PAM 后, PAM 就能够回报用户验证的结果 (成功或失败)。由于 PAM 仅是一套验证的机制,又可以提供给其他程序所调用引用,因此不论你使用什么程序,都可以使用 PAM 来进行验证,如此一来,就能够让帐号密码或者是其他方式的验证具有一致的结果!也让程序员方便处理验证的问题喔! (注5)
如上述的图标, PAM 是一个独立的 API 存在,只要任何程序有需求时,可以向 PAM 发出验证要求的通知, PAM 经过一连串的验证后,将验证的结果回报给该程序,然后该程序就能够利用验证的结果来进行可登录或显示其他无法使用的消息。 这也就是说,你可以在写程序的时候将 PAM 模块的功能加入,就能够利用 PAM 的验证功能啰。 因此目前很多程序都会利用 PAM 喔!所以我们才要来学习他啊!
PAM 用来进行验证的数据称为模块 (Modules),每个 PAM 模块的功能都不太相同。举例来说, 还记得我们在本章使用 passwd 指令时,如果随便输入字典上面找的到的字符串, passwd 就会回报错误信息了!这是为什么呢?这就是 PAM 的 pam_cracklib.so 模块的功能!他能够判断该密码是否在字典里面! 并回报给密码修改程序,此时就能够了解你的密码强度了。
所以,当你有任何需要判断是否在字典当中的密码字符串时,就可以使用 pam_cracklib.so 这个模块来验证! 并根据验证的回报结果来撰写你的程序呢!这样说,可以理解 PAM 的功能了吧?没错! PAM 的模块也是很重要的一环!
PAM 借由一个与程序相同文件名的设置档来进行一连串的认证分析需求。我们同样以 passwd 这个指令的调用 PAM 来说明好了。 当你运行 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的模块与该模块的参数。 底下我们先来谈谈验证类别与控制标准这两项数据吧!
验证类别主要分为四种,分别说明如下:
这四个验证的类型通常是有顺序的,不过也有例外就是了。 会有顺序的原因是,(1)我们总是得要先验证身份 (auth) 后, (2)系统才能够借由用户的身份给予适当的授权与权限设置 (account),而且(3)登录与注销期间的环境才需要设置, 也才需要记录登录与注销的信息 (session)。如果在运作期间需要密码修订时,(4)才给予 password 的类别。这样说起来, 自然是需要有点顺序吧!
那么『验证的控制旗标(control flag)』又是什么?简单的说,他就是『验证通过的标准』啦! 这个字段在管控该验证的放行方式,主要也分为四种控制方式:
如果将这些控制旗标以图标的方式配合成功与否的条件绘图,会有点像底下这样:
程序运作过程中遇到验证时才会去调用 PAM ,而 PAM 验证又分很多类型与控制,不同的控制旗标所回报的消息并不相同。 如上图所示, requisite 失败就回报了并不会继续,而 sufficient 则是成功就回报了也不会继续。 至于验证结束后所回报的信息通常是『succes 或 failure 』而已,后续的流程还需要该程序的判断来继续运行才行。
谈完了设置档的语法后,现在让我们来查阅一下 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 模块,每个模块的功能都不太相同,详细的模块情报可以在你的系统中找到:
例如鸟哥使用未 update 过的 CentOS 5.2 ,pam_nologin 说明文档档在: /usr/share/doc/pam-0.99.6.2/txts/README.pam_nologin。你可以自行查阅一下该模块的功能。 鸟哥这里仅简单介绍几个较常使用的模块,详细的信息还得要您努力查阅参考书呢! ^_^
了解了这些模块的大致功能后,言归正传,讨论一下 login 的 PAM 验证机制流程是这样的:
总之,就是依据验证类别 (type) 来看,然后先由 login 的设置值去查阅,如果出现『 include system-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 私房菜服务器篇 |
除了前一小节谈到的 /etc/securetty 会影响到 root 可登录的安全终端机, /etc/nologin 会影响到一般用户是否能够登录的功能之外,我们也知道 PAM 相关的设置档在 /etc/pam.d , 说明文档在 /usr/share/doc/pam-(版本) ,模块实际在 /lib/security/ 。那么还有没有相关的 PAM 文件呢? 是有的,主要都在 /etc/security 这个目录内!我们底下介绍几个可能会用到的设置档喔!
我们在第十一章谈到的 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 有个特殊的地方,由于他是在程序调用时才予以设置的,因此你修改完成的数据, 对于已登录系统中的用户是没有效果的,要等他再次登录时才会生效喔!另外, 上述的设置请在测试完成后立刻注解掉,否则下次这两个用户登录就会发生些许问题啦! ^_^
如果发生任何无法登录或者是产生一些你无法预期的错误时,由于 PAM 模块都会将数据记载在 /var/log/secure 当中,所以发生了问题请务必到该文件内去查找一下问题点!举例来说, 我们在 limits.conf 的介绍内的范例二,就有谈到多重登录的错误可以到 /var/log/secure 内查阅了! 这样你也就知道为何第二个 pro1 无法登录啦!^_^
谈了这么多的帐号问题,总是该要谈一谈,那么如何针对系统上面的用户进行查找吧? 想几个状态,如果你在 Linux 上面操作时,刚好有其他的用户也登录主机,你想要跟他对谈,该如何是好? 你想要知道某个帐号的相关信息,该如何查阅?呼呼!底下我们就来聊一聊~
如何查找一个用户的相关数据呢?这还不简单,我们之前就提过了 id, finger 等指令了,都可以让您了解到一个用户的相关信息啦!那么想要知道用户到底啥时候登录呢? 最简单可以使用 last 检查啊!这个玩意儿我们也在 第十一章 bash 提过了, 您可以自行前往参考啊!简单的很。
那如果你想要知道目前已登录在系统上面的用户呢?可以通过 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 ....(以下省略)....
这样就能够知道每个帐号的最近登录的时间啰~ ^_^
那么我是否可以跟系统上面的用户谈天说地呢?当然可以啦!利用 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..."
然后你就会发现所有的人都会收到这个短信呢!
使用 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> 指的是每封邮件的左边那个数字啦!而几个比较常见的指令是:
指令 | 意义 |
h | 列出信件标头;如果要查阅 40 封信件左右的信件标头,可以输入『 h 40 』 |
d | 删除后续接的信件号码,删除单封是『 d10 』,删除 20~40 封则为『 d20-40 』。 不过,这个动作要生效的话,必须要配合 q 这个指令才行(参考底下说明)! |
s | 将信件保存成文件。例如我要将第 5 封信件的内容存成 ~/mail.file:『s 5 ~/mail.file』 |
x | 或者输入 exit 都可以。这个是『不作任何动作离开 mail 程序』的意思。 不论你刚刚删除了什么信件,或者读过什么,使用 exit 都会直接离开 mail,所以刚刚进行的删除与阅读工作都会无效。 如果您只是查阅一下邮件而已的话,一般来说,建议使用这个离开啦!除非你真的要删除某些信件。 |
q | 相对于 exit 是不动作离开, q 则会进行两项动作: 1. 将刚刚删除的信件移出 mailbox 之外; 2. 将刚刚有阅读过的信件存入 ~/mbox ,且移出 mailbox 之外。鸟哥通常不很喜欢使用 q 离开, 因为,很容易忘记读过什么咚咚~导致信件给他移出 mailbox 说~ |
由于读过的信件若使用『 q 』来离开 mail 时,会将该信件移动到 ~/mbox 中,所以你可以这样想像: /var/spool/mail/vbird1 为 vbird1 的『新件匣』,而 /home/vbird1/mbox 则为『收件匣』的意思。 那如何读取 /home/vbird1/mbox 呢?就使用『mail -f /home/vbird1/mbox』即可。
一般来说,我们不很建议大家使用手动的方式来添加用户,为什么呢? 因为用户的创建涉及到 GID/UID 等权限的关系,而且,与文件/目录的权限也有关系, 使用 useradd 可以帮我们自动设置好 UID/GID 家目录以及家目录相关的权限设置, 但是,手动来增加的时候,有可能会忘东忘西,结果导致一些困扰的发生。
不过,要了解整个系统,最好还是手动来修改过比较好,至少我们的帐号问题可以完全依照自己的意思去修订, 而不必迁就于系统的默认值啊!但是,还是要告诫一下朋友们,要手动设置帐号时, 您必须要真的很了解自己在作什么,尤其是与权限有关的设置方面喔!好吧!底下就让我们来玩一玩啰~ ^_^
既然要手动修改帐号的相关设置档,那么一些检查群组、帐号相关的指令就不可不知道啊~ 尤其是那个密码转换的 pwconv 及 pwuconv 这两个玩意~可重要的很呢!底下我们稍微介绍一下这些指令吧!
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 这个指令的啦!
这个指令主要的目的是在『将 /etc/passwd 内的帐号与密码,移动到 /etc/shadow 当中!』 早期的 Unix 系统当中并没有 /etc/shadow 呢,所以,用户的登录密码早期是在 /etc/passwd 的第二栏,后来为了系统安全,才将密码数据移动到 /etc/shadow 内的。使用 pwconv 后,可以:
一般来说,如果您正常使用 useradd 增加用户时,使用 pwconv 并不会有任何的动作,因为 /etc/passwd 与 /etc/shadow 并不会有上述两点问题啊! ^_^。不过,如果手动设置帐号,这个 pwconv 就很重要啰!
相对于 pwconv , pwunconv 则是『将 /etc/shadow 内的密码栏数据写回 /etc/passwd 当中, 并且删除 /etc/shadow 文件。』这个指令说实在的,最好不要使用啦! 因为他会将你的 /etc/shadow 删除喔!如果你忘记备份,又不会使用 pwconv 的话,粉严重呢!
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 这个指令,所以您还是得要了解一下这个指令用途!
在我们了解了 UID/GID 与帐号的关系之后,基本上,您应该了解了,为啥我们不建议使用纯数字的帐号了!因为很多时候,系统会搞不清楚那组数字是『帐号』还是『 UID 』,这不是很好啦~也因此,在早期某些版本底下,是没有办法使用数字来创建帐号的。例如在 Red Hat 9 的环境中, 使用『 useradd 1234 』他会显示『 useradd: invalid user name '1234' 』了解了吗?
不过,有的时候,长官的命令难为啊 @_@ 有时还是得要创建这方面的帐号的,那该如何是好? 呵呵!当然可以手动来创建这样的帐号啦!不过,为了系统安全起见,鸟哥还是不建议使用纯数字的帐号的啦! 因此,底下的范例当中,我们使用手动的方式来创建一个名为 normaluser 的帐号, 而且这个帐号属于 normalgroup 这个群组。OK!那么整个步骤该如何是好呢? 由前面的说明来看,您应该了解了帐号与群组是与 /etc/group, /etc/shadow, /etc/passwd, /etc/gshadow 有关,因此,整个动作是这样的:
1. 创建群组 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 都存在这个群组才行!搞定群组啰! 2. 创建 normaluser 这个帐号,假设 UID 700 没被使用掉! [root@www ~]# vi /etc/passwd # 在最后一行加入底下这一行! normaluser:x:700:520::/home/normaluser:/bin/bash 3. 同步化密码,并且创建该用户的密码 [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. 4. 创建用户家目录,并且修订权限! [root@www ~]# cp -a /etc/skel /home/normaluser [root@www ~]# chown -R normaluser:normalgroup /home/normaluser [root@www ~]# chmod 700 /home/normaluser
别怀疑!这样就搞定了一个帐号的设置了! 从此以后,你可以创建任何名称的帐号啰~不过,还是不建议您设置一些很怪很怪的帐号名称啦!
由于 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 这个文件即可!鸟哥创建这个文件里面共有十行,你可以自行创建该文件! 内容每一行一个帐号。注意,最终的结果会是每个帐号具有与帐号相同的密码,且初次登录后, 必须要重新设置密码后才能够再次登录使用系统资源!
[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. ....(后面省略)....
这支简单的脚本你可以在按如下的链接下载:
另外,鸟哥的 script 是在 zh_TW.big5 的语系下创建的,如果你需要转成万国码 (utf8) 的编码格式, 请下载上述文件后,利用第十章谈到的 iconv 来处理语系的问题!
前一小节的内容已经可以满足很多朋友的帐号建置方法了,不过,某些时候上述的 script 还是很麻烦! 因为需要手动编辑 account1.txt 嘛!如果是类似学校单位这种学号非常类似的帐号时,有没有更快的方案? 此外,如果需要每个班级同属于一个群组,不同班级的群组不同,又该如何建置?这是比较麻烦啦!
目前很多网站都有提供大量创建帐号的工具,例如台南县网中心的卧龙大师:
提供的好用的 cmpwd 程序,但是小三大师的程序仅供学术单位使用,一般个人是无权使用的(参考上述链接的授权)。 不过,其实我们也可以利用简单的 script 来帮我们达成喔!例如底下这支程序, 他的运行结果与小三大师提供的程序差不多啦~但是因为我是直接以 useradd 来添加的, 所以,即使不了解 UID ,也是可以适用的啦~整支程序的特色是:
运行方法也简单的要命~请自行参考的啦!不再多说~使用时请注意,不要在公家使用的主机上面进行测试,因为..... 这支程序会大量创建帐号嘛!^_^
#!/bin/bash # # 这支程序主要在帮您创建大量的帐号之用,更多的使用方法请参考: # http://vbird.org.cn/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 』那行!这支脚本可以在底下链接下载:
如果仅是测试而已,想要将刚刚创建的用户整个删除,则可以使用如下的脚本来进行删除!
[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
总之,帐号管理是很重要的!希望上面的说明能够对大家有点帮助啦!
[root@www ~]# grep mail /etc/group [root@www ~]# grep youcan /etc/group [root@www ~]# groupadd youcan可发现 youcan 尚未被创建,因此如上表所示,我们主动去创建这个群组啰。
[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
[root@www ~]# vim loginuser.sh #!/bin/bash for username in youlog1 youlog2 youlog3 do useradd -G youcan -s /bin/bash -m $username echo $username | passwd --stdin $username done [root@www ~]# sh loginuser.sh