Linux账号管理与ACL权限设置

1. Linux 的账号与群组

1.1 使用者标识符: UID 与 GID

每个登陆的使用者至少都会取得两个 ID ,一个是使用者 ID (User ID ,简称 UID)、一个是群组 ID (Group ID ,简称 GID)。

1.2 用户账号

Linux 系统上面的用户如果需要登陆主机以取得 shell 的环境来工作时,输入账号与口令后登陆,系统帮你处理了什么呢?

  1. 先找寻 /etc/passwd 里面是否有你输入的账号?如果没有则跳出,如果有的话则将该账号对应的 UID 与 GID (在 /etc/group 中) 读出来,另外,该账号的家目录与 shell 配置也一并读出;
  2. 再来则是核对口令表啦!这时 Linux 会进入 /etc/shadow 里面找出对应的账号与 UID,然后核对一下你刚刚输入的口令与里头的口令是否相符?
  3. 如果一切都 OK 的话,就进入 Shell 控管的阶段啰!

/etc/passwd 文件结构

  1. 每一行都代表一个账号,有几行就代表有几个账号在你的系统中。
  2. 里头很多账号本来就是系统正常运行所必须要的,我们可以简称他为系统账号, 例如 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
  1. 账号名称:
    就是账号啦!用来对应 UID 的。例如 root 的 UID 对应就是 0 (第三字段);

  2. 口令:
    早期 Unix 系统的口令就是放在这字段上!但是因为这个文件的特性是所有的程序都能够读取,这样一来很容易造成口令数据被窃取, 因此后来就将这个字段的口令数据给他改放到 /etc/shadow 中了。所以这里你会看到一个『 x !

  3. UID:
    这个就是使用者标识符。当 UID 是 0 时,代表这个账号是『系统管理员』!1~499
    是系统账号,默认500以下的数字让给系统作为保留账号只是一个习惯。500以上给一般使用者。
  4. GID:
    这个与 /etc/group 有关!

  5. 用户信息说明栏:
    这个字段基本上并没有什么重要用途,只是用来解释这个账号的意义而已!不过,如果您提供使用 finger 的功能时, 这个字段可以提供很多的信息!

  6. 家目录:
    这是用户的家目录,以上面为例, root 的家目录在 /root ,所以当 root 登陆之后,就会立刻跑到 /root 目录里!

  7. Shell:
    当用户登陆系统后就会取得一个Shell 来与系统的核心沟通以进行用户的操作任务。那为何默认 shell 会使用 bash 呢?就是在这个字段指定的! 这里比较需要注意的是,有一个 shell 可以用来替代成让账号无法取得 shell 环境的登陆动作!那就是 /sbin/nologin 这个东西!这也可以用来制作纯 pop 邮件账号者的数据呢!

/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:::
  1. 账号名称:
    由于口令也需要与账号对应啊~因此,这个文件的第一栏就是账号,必须要与 /etc/passwd 相同才行!

  2. 口令:
    这个字段内的数据才是真正的口令,而且是经过编码的口令 (加密) 啦! 你只会看到有一些特殊符号的字母就是了!需要特别留意的是,虽然这些加密过的口令很难被解出来, 但是『很难』不等于『不会』,所以,这个文件的默认权限是『-rw——-』或者是『-r——–』,亦即只有 root 才可以读写就是了!

  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 字段相比)
    第四个字段记录了:这个账号的口令在最近一次被更改后需要经过几天才可以再被变更!如果是 0 的话, 表示口令随时可以更动的意思。这的限制是为了怕口令被某些人一改再改而设计的!如果配置为 20 天的话,那么当你配置了口令之后, 20 天之内都无法改变这个口令呦!

  5. 口令需要重新变更的天数:(与第 3 字段相比)
    经常变更口令是个好习惯!为了强制要求用户变更口令,这个字段可以指定在最近一次更改口令后, 在多少天数内需要再次的变更口令才行。你必须要在这个天数内重新配置你的口令,否则这个账号的口令将会『变为过期特性』。 而如果像上面的 99999 (计算为 273 年) 的话,那就表示,呵呵,口令的变更没有强制性之意。

  6. 口令需要变更期限前的警告天数:(与第 5 字段相比)
    当账号的口令有效期限快要到的时候 (第 5 字段),系统会依据这个字段的配置,发出『警告』言论给这个账号,提醒他『再过 n 天你的口令就要过期了,请尽快重新配置你的口令呦!』,如上面的例子,则是口令到期之前的 7 天之内,系统会警告该用户。

  7. 口令过期后的账号宽限时间(口令失效日):(与第 5 字段相比)
    口令有效日期为『升级日期(第3字段)』+『重新变更日期(第5字段)』,过了该期限后用户依旧没有升级口令,那该口令就算过期了。 虽然口令过期但是该账号还是可以用来进行其他工作的,包括登陆系统取得 bash 。不过如果口令过期了, 那当你登陆系统时,系统会强制要求你必须要重新配置口令才能登陆继续使用喔,这就是口令过期特性。
    那这个字段的功能是什么呢?是在口令过期几天后,如果使用者还是没有登陆更改口令,那么这个账号的口令将会『失效』, 亦即该账号再也无法使用该口令登陆了。要注意口令过期与口令失效并不相同。

  8. 账号失效日期:
    这个日期跟第三个字段一样,都是使用 1970 年以来的总日数配置。这个字段表示: 这个账号在此字段规定的日期之后,将无法再使用。 就是所谓的『账号失效』,此时不论你的口令是否有过期,这个『账号』都不能再被使用! 这个字段会被使用通常应该是在『收费服务』的系统中,你可以规定一个日期让该账号不能再使用啦!

  9. 保留:
    最后一个字段是保留的,看以后有没有新功能加入。

1.3 有效与初始用户组:groups,newgrp

/etc/passwd 的第四栏就是的 GID

/etc/group 文件结构

这个文件就是在记录 GID 与组名的对应了~

[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. 组名:
就是组名啦!

  1. 群组口令:
    通常不需要配置,这个配置通常是给『群组管理员』使用的,目前很少有这个机会配置群组管理员啦! 同样的,口令已经移动到 /etc/gshadow 去,因此这个字段只会存在一个『x』而已;

  2. GID:
    就是群组的 ID 啊。我们 /etc/passwd 第四个字段使用的 GID 对应的群组名,就是由这里对应出来的!

  3. 此群组支持的账号名称:
    我们知道一个账号可以加入多个群组,那某个账号想要加入此群组时,将该账号填入这个字段即可。 举例来说,如果我想要让 dmtsai 也加入 root 这个群组,那么在第一行的最后面加上『,dmtsai』,注意不要有空格, 使成为『 root:x:0:root,dmtsai 』就可以啰~

下图中, root 的 UID 是 0 ,而 GID 也是 0 ,去找 /etc/group 可以知道 GID 为 0 时的组名就是 root 哩。 至于口令的寻找中,会找到 /etc/shadow 与 /etc/passwd 内同账号名称的那一行,就是口令相关数据啰。
image
图 1.3.1 、账号相关文件之间的 UID/GID 与口令相关性示意图

有效群组(effective group)与初始群组(initial group)

初始群组:每个使用者在他的 /etc/passwd 里面的第四栏有所谓的 GID ,那个 GID 就是所谓的『初始群组 (initial group) ,当用户一登陆系统,立刻就拥有这个群组的相关权限。
有效用户组:可以新建文件的用户组。

groups: 有效与支持群组的观察

如果我以 dmtsai 这个使用者的身份登陆后,该如何知道我所有支持的群组呢? 很简单啊,直接输入 groups 就可以了!结果像这样:

[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

/etc/gshadow文件结构

[root@www ~]# head -n 4 /etc/gshadow
root:::root
bin:::root,bin,daemon
daemon:::root,bin,daemon
sys:::root,bin,adm
  1. 组名
  2. 口令栏,同样的,开头为 ! 表示无合法口令,所以无群组管理员
  3. 群组管理员的账号 (相关信息在 gpasswd 中介绍)
  4. 该群组的所属账号 (与 /etc/group 内容相同!)

2 账号管理

2.1 新增与删除用户: useradd, 相关配置文件, passwd, usermod, userdel

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 这些默认值主要会帮我们处理几个项目:

  1. 在 /etc/passwd 里面创建一行与账号相关的数据,包括创建 UID/GID/家目录等;
  2. 在 /etc/shadow 里面将此账号的口令相关参数填入,但是尚未有口令;
  3. 在 /etc/group 里面加入一个与账号名称一模一样的组名;
  4. 在 /home 底下创建一个与账号同名的目录作为用户家目录,且权限为 700
  5. 由于在 /etc/shadow 内仅会有口令参数而不会有加密过的口令数据,因此我们在创建使用者账号时, 还需要使用==passwd 账号==来给予口令才算是完成了用户创建的流程。
系统账号 (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 的默认值可以使用底下的方法呼叫出来,也就是说,使用useradd 账号来创建账户时,默认使用的是以下参考文件的内容

[root@www ~]# useradd -D

GROUP=100       <==默认的群组
HOME=/home      <==默认的家目录所在目录
INACTIVE=-1     <==口令失效日,在 shadow 内的第 7EXPIRE=         <==账号失效日,在 shadow 内的第 8SHELL=/bin/bash     <==默认的 shell
SKEL=/etc/skel      <==用户家目录的内容数据参考目录
CREATE_MAIL_SPOOL=yes   <==是否主动帮使用者创建邮件信箱(mailbox)

这个数据其实是==由 /etc/default/useradd 呼叫出来==的!

  1. GROUP=100:新建账号的初始群组使用 GID 为 100,系统上面 GID 为 100 者即是 users 这个群组者,此配置项目指的就是让新设使用者账号的初始群组为 users 这一个的意思。在 ==CentOS 上面默认的群组为与账号名相同的群组==。
  2. HOME=/home:用户家目录的基准目录(basedir)
    用户的家目录通常是与账号同名的目录,这个目录将会摆放在此配置值的目录后。所以 vbird1 的家目录就会在 /home/vbird1/ 了!

  3. INACTIVE=-1:口令过期后是否会失效的配置值。
    我们在 shadow 文件结构当中谈过,第七个字段的配置值将会影响到口令过期后, 在多久时间内还可使用旧口令登陆。这个项目就是在指定该日数啦!如果是 0 代表口令过期立刻失效, 如果是 -1 则是代表口令永远不会失效,如果是数字,如 30 ,则代表过期 30 天后才失效。

  4. EXPIRE=:账号失效的日期。就是 shadow 内的第八字段,你可以直接配置账号在哪个日期后就直接失效,而不理会口令的问题。 通常不会配置此项目,但如果是付费的会员制系统,或许这个字段可以配置喔!

  5. SHELL=/bin/bash:默认使用的 shell 程序文件名。系统默认的 shell 就写在这里。假如你的系统为 mail server ,你希望每个账号都只能使用 email 的收发信件功能, 而不许用户登陆系统取得 shell ,那么可以将这里配置为 /sbin/nologin ,如此一来,新建的使用者默认就无法登陆! 也免去后续使用 usermod 进行修改的手续!

  6. SKEL=/etc/skel:用户家目录参考基准目录。这个就是指定用户家目录的参考基准目录啰~举我们的范例一为例, vbird1 家目录 /home/vbird1 内的各项数据,都是由 /etc/skel 所复制过去的~所以呢,未来如果我想要让新增使用者时,该用户的环境变量 ~/.bashrc 就配置妥当的话,您可以到 /etc/skel/.bashrc 去编辑一下,也可以创建 /etc/skel/www 这个目录,那么未来新增使用者后,在他的家目录下就会有 www 那个目录了!

  7. CREATE_MAIL_SPOOL=yes:创建使用者的 mailbox

  8. 你可以使用『 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,意即小于 500UID 为系统保留
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 上的账号时,至少会参考:

  1. /etc/default/useradd
  2. /etc/login.defs
  3. /etc/skel/*

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.  <==竟然还是成功修改了!

范例:使用 standard input 创建用户的口令

[root@www ~]# echo "abc543CC" | passwd --stdin vbird2
Changing password for user vbird2.
passwd: all authentication tokens updated successfully.

这个动作会直接升级用户的口令而不用再次的手动输入!好处是方便处理,缺点是这个口令会保留在命令中, 未来若系统被攻破,人家可以在 /root/.bash_history 找到这个口令呢!

范例:管理 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 的账号失效,观察完毕后再让她失效==

[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::
# 口令字段恢复正常!

那如果我想要让某个账号暂时无法使用口令登陆主机呢?举例来说, vbird2 这家伙最近老是胡乱在主机乱来, 所以我想要暂时让她无法登陆的话,最简单的方法就是让她的口令变成不合法 (shadow 第 2 字段长度变掉)! 处理的方法就更简单的!

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(谨慎!)

这个功能就太简单了,目的在删除用户的相关数据,而用户的数据有:

  1. 用户账号/口令相关参数:/etc/passwd, /etc/shadow
  2. 使用者群组相关参数:/etc/group, /etc/gshadow
  3. 用户个人文件数据: /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, 十六章) 之类的文件。 所以,如果想要完整的将某个账号完整的移除,最好可以在下达 userdel -r username 之前, 先以『 find / -user username 』查出整个系统内属于 username 的文件,然后再加以删除吧!

2.2 新增与删除用户组

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 来决定!

groupmod

跟 usermod 类似的,这个命令仅是在进行 group 相关参数的修改而已。

[root@www ~]# groupmod [-g gid] [-n group_name] 群组名
选项与参数:
-g  :修改既有的 GID 数字;
-n  :修改既有的组名

范例一:将刚刚上个命令创建的 group1 名称改为 mygroup , GID201
[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) 的 initial group 使用该群组!』 如果查阅一下,你会发现在 /etc/passwd 内的 vbird1 第四栏的 GID 就是 /etc/group 内的 vbird1 那个群组的 GID ,所以啰,当然无法删除~否则 vbird1 这个用户登陆系统后, 就会找不到 GID ,那可是会造成很大的困扰的!那么如果硬要删除 vbird1 这个群组呢? 你『必须要确认 /etc/passwd 内的账号没有任何人使用该群组作为 initial group 』才行喔!所以,你可以:

  1. 修改 vbird1 的 GID ,或者是:
  2. 删除 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 啰~

2.3 账号管理实例

账号管理不是随意建置几个账号就算了!有时候我们需要考虑到一部主机上面可能有多个账号在协同工作! 举例来说,在大学任教时,我们学校的专题生是需要分组的,这些同一组的同学间必须要能够互相修改对方的数据文件, 但是同时这些同学又需要保留自己的私密数据,因此直接公开家目录是不适宜的。那该如何是好? 为此,我们底下提供几个例子来让大家思考看看啰:

任务一:单纯的完成上头交代的任务,假设我们需要的账号数据如下,你该如何实作?
image
处理的方法如下所示:

#

先处理账号相关属性的数据:
[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 来给予,这样该账号就无法登陆啰! 这样是否理解啊!

3 主机的具体权限规划:ACL 的使用

3.1 什么是 ACL

ACL 是 Access Control List 的缩写,主要的目的是在提供传统的 owner,group,others 的 read,write,execute 权限之外的细部权限配置。ACL 可以针对单一使用者,单一文件或目录来进行 r,w,x 的权限规范,对于需要特殊权限的使用状况非常有帮助。

那 ACL 主要可以针对哪些方面来控制权限呢?他主要可以针对几个项目:

  1. 使用者 (user):可以针对使用者来配置权限;
  2. 群组 (group):针对群组为对象来配置其权限;
  3. 默认属性 (mask):还可以针对在该目录下在创建新文件/目录时,规范新数据的默认权限。

3.2 如何启动ACL

由于 ACL 是传统的 Unix-like 操作系统权限的额外支持项目,因此要使用 ACL 必须要有文件系统的支持才行。目前绝大部分的文件系统都有支持 ACL 的功能.

[root@www ~]# mount  <==直接查阅挂载参数的功能
/dev/vda1 on / type ext3 (rw,noatime,acl,user_xattr)
proc on /proc type proc (rw)
sysfs on /sys type sysfs (rw)
devpts on /dev/pts type devpts (rw,mode=0620,gid=5)
none on /proc/sys/fs/binfmt_misc type binfmt_misc (rw)

3.3 ACL 的配置技巧: getfacl, setfacl

  1. getfacl:取得某个文件/目录的 ACL 配置项目;
  2. setfacl:配置某个目录/文件的 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 吧!

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 啦!然后再分别依据不同的使用者/群组去规范她们的权限就是了。

3.4 账户管理实例

任务:我的使用者 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 是必须要存在的1

但接下来有个困扰的问题发生了!假如任务一的 myuser1 是 projecta 这个项目的助理,他需要这个项目的内容, 但是他『不可以修改』项目目录内的任何数据!那该如何是好?你或许可以这样做:

将 myuser1 加入 projecta 这个群组的支持,但是这样会让 myuser1 具有完整的 /srv/projecta 的权限, myuser1 是可以删除该目录下的任何数据的!这样是有问题的;
将 /srv/projecta 的权限改为 2775 ,让 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 檔名 』即可啦! 太简单了!鸟哥就不另外介绍了!请自行测试测试吧!

4 用户身份切换

4.1 su

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 就这样简单的介绍完毕,总结一下他的用法是这样的:

  1. 若要完整的切换到新使用者的环境,必须要使用『 su - username 』或『 su -l username 』, 才会连同 PATH/USER/MAIL 等变量都转成新用户的环境;

  2. 如果仅想要运行一次 root 的命令,可以利用『 su - -c “命令串” 』的方式来处理;

  3. 使用 root 切换成为任何使用者时,并不需要输入新用户的口令。

虽然使用 su 很方便啦,不过缺点是,当我的主机是多人共管的环境时,如果大家都要使用 su 来切换成为 root 的身份,那么不就每个人都得要知道 root 的口令,这样口令太多人知道可能会流出去, 很不妥当呢!怎办?透过 sudo 来处理即可!

4.2 sudo

4.2.1 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 的运行是这样的流程:

  1. 当用户运行 sudo 时,系统于 /etc/sudoers 文件中搜寻该使用者是否有运行 sudo 的权限;
  2. 若使用者具有可运行 sudo 的权限后,便让使用者『输入用户自己的口令』来确认;
  3. 若口令输入成功,便开始进行 sudo 后续接的命令(但 root 运行 sudo 时,不需要输入口令);
  4. 若欲切换的身份与运行者身份相同,那也不需要输入口令。

所以说,sudo 运行的重点是:『==能否使用 sudo 必须要看 /etc/sudoers 的配置值==, 而可使用 sudo 者是透过输入用户自己的口令来运行后续的命令串』喔!由于能否使用与 /etc/sudoers 有关, 所以我们当然要去编辑 sudoers 文件啦!不过,因为该文件的内容是有一定的规范的,因此直接使用 vi 去编辑是不好的。 此时,我们得要透过 visudo 去修改这个文件喔!

4.2.2 visudo 与 /etc/sudoers

从上面的说明我们可以知道,除了 root 之外的其他账号,若想要使用 sudo 运行属于 root 的权限命令,则 root 需要先使用 visudo 去修改 /etc/sudoers ,让该账号能够使用全部或部分的 root 命令功能。为什么要使用 visudo 呢?这是因为 /etc/sudoers 是有配置语法的,如果配置错误那会造成无法使用 sudo 命令的不良后果。因此才会使用 visudo 去修改, 并在结束离开修改画面时,系统会去检验 /etc/sudoers 的语法就是了。

一般来说,visudo 的配置方式有几种简单的方法喔,底下我们以几个简单的例子来分别说明:

a.单一用户可进行 root 所有命令,与 sudoers 文件语法:

假如我们要让 vbird1 这个账号可以使用 root 的任何命令,那么可以简单的这样进行修改即可:

[root@www ~]# visudo
....(前面省略)....
root    ALL=(ALL)       ALL  <==找到这一行,大约在 76 行左右
vbird1  ALL=(ALL)       ALL  <==这一行是你要新增的!
....(前面省略)....

有趣吧!其实 visudo 只是利用 vi 将 /etc/sudoers 文件呼叫出来进行修改而已,所以这个文件就是 /etc/sudoers 啦! 这个文件的配置其实很简单,如上面所示,如果你找到 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 这个用户的『操守』才行!否则随便配置一个用户,他恶搞系统怎办?另外,一个一个配置太麻烦了, 能不能使用群组的方式来配置呢?参考底下的方式吧。

b.利用群组以及免口令的功能处理 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 啦!该关键词是免除口令输入的意思喔!

c.有限制的命令操作:

上面两点都会让使用者能够利用 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 的口令!很有用处的!

d.透过别名建置 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 这两行即可!配置方面会比较简单有弹性喔!

e.sudo 的时间间隔问题:

或许您已经发现了,那就是,如果我使用同一个账号在短时间内重复操作 sudo 来运行命令的话, 在第二次运行 sudo 时,并不需要输入自己的口令!sudo 还是会正确的运行喔!为什么呢? 第一次运行 sudo 需要输入口令,是担心由于用户暂时离开座位,但有人跑来你的座位使用你的账号操作系统之故。 所以需要你输入一次口令重新确认一次身份。

两次运行 sudo 的间隔在五分钟内,那么再次运行 sudo 时就不需要再次输入口令了, 这是因为系统相信你在五分钟内不会离开你的作业,所以运行 sudo 的是同一个人!呼呼!真是很人性化的设计啊~ ^_^。不过如果两次 sudo 操作的间隔超过 5 分钟,那就得要重新输入一次你的口令了。

另外要注意的是,因为使用一般账号时,理论上不会使用到 /sbin, /usr/sbin 等目录内的命令,所以 $PATH 变量不会含有这些目录,因此很多管理命令需要使用绝对路径来下达比较妥当喔!

f.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 口令不会外流,用户的管理也变的非常方便! 这也是实务上面多人共管一部主机时常常使用的技巧呢!这样管理确实方便,不过还是要强调一下大前提, 那就是『这些你加入的使用者,全部都是你能够信任的用户』!

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值