Linux账户体系分为用户和群组,一个用户可以属于多个群组.而Linux里面一切皆是文件,而对文件的权限分为三类:拥有者,群组,其他.

针对不同的用户需求,应该创建不同的账户和群组.使它们只能针对特定的文件或目录拥有权限,这样最大限度的保证系统的安全.

UID和GID

每个Linux账户拥有至少两个ID,UID(User id)和GID(Group id).它们分别表示用户id和群组id.

Linux主机通过这两个id识别当前用户拥有的权限有哪些.

用户和群信息的管理文件

/etc/passwd

/etc/passwd保存着当前主机上所有的用户信息.

这个文件的构造是这样的:每一行都代表一个账号,有几行就代表有几个账号在你的系统中! 不过需要特别留意的是,里头很多账号本来就是系统正常运行所必须要的,我们可以简称他为系统账号, 例如 bin, daemon, adm, nobody 等等,这些账号请不要随意的杀掉他呢!

1
2
3
4
5
6
[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
[账号名称]:[口令]:[UID]:[GID]:[用户信息说明栏]:[家目录]:[Shell]

注意:上面👆每一行代表一个用户.而每一行被:分割开,拥有不同的含义:

  1. 账号名称
    就是账号啦!用来对应 UID 的。例如 root 的 UID 对应就是 0 (第三字段);

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

  3. UID:

    这个就是使用者标识符啰!通常 Linux 对于 UID 有几个限制需要说给您了解一下:

    id 范围 该 ID 使用者特性
    0 (系统管理员) 当 UID 是 0 时,代表这个账号是『系统管理员』! 所以当你要让其他的账号名称也具有 root 的权限时,将该账号的 UID 改为 0 即可。 这也就是说,一部系统上面的系统管理员不见得只有 root 喔! 不过,很不建议有多个账号的 UID 是 0 啦~
    1~499 (系统账号) 保留给系统使用的 ID,其实除了 0 之外,其他的 UID 权限与特性并没有不一样。默认 500 以下的数字让给系统作为保留账号只是一个习惯。 由于系统上面启动的服务希望使用较小的权限去运行,因此不希望使用 root 的身份去运行这些服务, 所以我们就得要提供这些运行中程序的拥有者账号才行。这些系统账号通常是不可登陆的, 所以才会有我们在第十一章提到的 /sbin/nologin 这个特殊的 shell 存在。 根据系统账号的由来,通常系统账号又约略被区分为两种: 199:由 distributions 自行创建的系统账号; 100499:若用户有系统账号需求时,可以使用的账号 UID。
    500~65535 (可登陆账号) 给一般使用者用的。事实上,目前的 linux 核心 (2.6.x 版)已经可以支持到 4294967295 (2^32-1) 这么大的 UID 号码喔!

    上面这样说明可以了解了吗?是的, UID 为 0 的时候,就是 root 呦!所以请特别留意一下你的 /etc/passwd 文件!

  4. GID
    这个与 /etc/group 有关!其实 /etc/group 的观念与 /etc/passwd 差不多,只是他是用来规范组名与 GID 的对应而已!

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

  6. 家目录
    这是用户的家目录,以上面为例, root 的家目录在 /root ,所以当 root 登陆之后,就会立刻跑到 /root 目录里头啦!呵呵! 如果你有个账号的使用空间特别的大,你想要将该账号的家目录移动到其他的硬盘去该怎么作? 没有错!可以在这个字段进行修改呦!默认的用户家目录在 /home/yourIDname

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

/etc/shadow

/etc/shadow保存着用户账户的口令,它的数据和/etc/passwd是对应的.它每一行表示一个用户的口令信息.

1
2
3
4
5
[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 才可以读写就是了!你得随时注意,不要不小心更动了这个文件的权限呢!

    另外,由于各种口令编码的技术不一样,因此不同的编码系统会造成这个字段的长度不相同。 举例来说,旧式的 DES 编码系统产生的口令长度就与目前惯用的 MD5 不同(注2)!MD5 的口令长度明显的比较长些。由于固定的编码系统产生的口令长度必须一致,因此『当你让这个字段的长度改变后,该口令就会失效(算不出来)』。 很多软件透过这个功能,在此字段前加上 ! 或 * 改变口令字段长度,就会让口令『暂时失效』了。

  3. 最近更动口令的日期:

    这个字段记录了『更动口令那一天』的日期,不过,很奇怪呀!在我的例子中怎么会是 14126 呢?呵呵,这个是因为计算 Linux 日期的时间是以 1970 年 1 月 1 日作为 1 而累加的日期,1971 年 1 月 1 日则为 366 啦! 得注意一下这个数据呦!上述的 14126 指的就是 2008-09-04 那一天啦!了解乎? 而想要了解该日期可以使用本章后面chage命令的帮忙!至于想要知道某个日期的累积日数, 可使用如下的程序计算:

    上述命令中,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. 保留
    最后一个字段是保留的,看以后有没有新功能加入。

/etc/group

/etc/group保存着主机所有群组的信息,

1
2
3
4
5
[root@www ~]# head -n 4 /etc/group
root:x:0:root
bin:x:1:root,bin,daemon
daemon:x:2:root,bin,daemon
sys:x:3:root,bin,adm
  1. 组名
    就是组名啦!
  2. 群组口令
    通常不需要配置,这个配置通常是给『群组管理员』使用的,目前很少有这个机会配置群组管理员啦! 同样的,口令已经移动到 /etc/gshadow 去,因此这个字段只会存在一个『x』而已;
  3. GID
    就是群组的 ID 啊。我们 /etc/passwd 第四个字段使用的 GID 对应的群组名,就是由这里对应出来的!
  4. 此群组支持的账号名称
    我们知道一个账号可以加入多个群组,那某个账号想要加入此群组时,将该账号填入这个字段即可。 举例来说,如果我想要让 dmtsai 也加入 root 这个群组,那么在第一行的最后面加上『,dmtsai』,注意不要有空格, 使成为『 root:X:0:root,dmtsai 』就可以啰~

/etc/group/etc/passwd/etc/shadow之间的关系如下图:

有效群组和初始群组

/etc/passwd中第四栏的GID表示的是用户的初始群组.当用户一登陆系统,立刻就拥有这个群组的相关权限的意思.

1
2
3
4
5
6
7
[root@www ~]# usermod -G users dmtsai  <==先配置好次要群组
[root@www ~]# grep dmtsai /etc/passwd /etc/group /etc/gshadow
/etc/passwd:dmtsai:x:503:504::/home/dmtsai:/bin/bash
/etc/group:users:x:100:dmtsai <==次要群组的配置
/etc/group:dmtsai:x:504: <==因为是初始群组,所以第四字段不需要填入账号
/etc/gshadow:users:::dmtsai <==次要群组的配置
/etc/gshadow:dmtsai:!::

仔细看到上面这个表格,在/etc/passwd里面,dmtsai 这个使用者所属的群组为 GID=504 ,搜寻一下 /etc/group 得到 504 是那个名为 dmtsai 的群组啦!这就是 initial group。因为是初始群组, 使用者一登陆就会主动取得,不需要在 /etc/group 的第四个字段写入该账号的!

但是非 initial group 的其他群组可就不同了。举上面这个例子来说,我将 dmtsai 加入 users 这个群组当中,由于 users 这个群组并非是 dmtsai 的初始群组,因此, 我必须要在 /etc/group 这个文件中,找到 users 那一行,并且将 dmtsai 这个账号加入第四栏, 这样 dmtsai 才能够加入 users 这个群组啊。

那么在这个例子当中,因为我的 dmtsai 账号同时支持 dmtsai 与 users 这两个群组, 因此,在读取/写入/运行文件时,针对群组部分,只要是 users 与 dmtsai 这两个群组拥有的功能, 我 dmtsai 这个使用者都能够拥有喔!这样瞭呼?不过,这是针对已经存在的文件而言, 如果今天我要创建一个新的文件或者是新的目录,请问一下,新文件的群组是 dmtsai 还是 users ?呵呵!这就得要检查一下当时的有效群组了 (effective group)。

可以通过groups查看当前用户所拥有的群组

1
2
3
4
5
[dmtsai@www ~]$ groups
dmtsai users
[dmtsai@www ~]$ touch test
[dmtsai@www ~]$ ll
-rw-rw-r-- 1 dmtsai dmtsai 0 Feb 24 17:26 test

groups命令输出的一个群组名就是当前用户的有效群组,用户创建的文件或目录都是属于这个群组的.

可以通过newgrp更改有效群组

1
2
3
4
5
6
7
[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

不过使用 newgrp 是有限制的,那就是你想要切换的群组必须是你已经有支持的群组。

/etc/gshadow

/etc/gshadow保存着群组口令和群主管理员信息.

1
2
3
4
5
[root@www ~]# head -n 4 /etc/gshadow
root:::root
bin:::root,bin,daemon
daemon:::root,bin,daemon
sys:::root,bin,adm

这个文件内同样还是使用冒号『:』来作为字段的分隔字符,而且你会发现,这个文件几乎与 /etc/group 一模一样啊!是这样没错~不过,要注意的大概就是第二个字段吧~第二个字段是口令栏, 如果口令栏上面是『!』时,表示该群组不具有群组管理员!至于第四个字段也就是支持的账号名称啰~ 这四个字段的意义为:

  1. 组名
  2. 口令栏,同样的,开头为 ! 表示无合法口令,所以无群组管理员
  3. 群组管理员的账号 (相关信息在 gpasswd 中介绍)
  4. 该群组的所属账号 (与 /etc/group 内容相同!)

以系统管理员的角度来说,这个 gshadow 最大的功能就是创建群组管理员啦! 那么什么是群组管理员呢?由于系统上面的账号可能会很多,但是我们 root 可能平时太忙碌,所以当有使用者想要加入某些群组时, root 或许会没有空管理。此时如果能够创建群组管理员的话,那么该群组管理员就能够将那个账号加入自己管理的群组中! 可以免去 root 的忙碌啦!

用户管理

useradd

useradd 用来创建新用户,并且可以指定用户的初始群组和所属群组.但它不能设定账户的口令!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[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: <==默认会创建一个与账号一模一样的群组名

范例二:假设我已知道我的系统当中有个组名为 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 确实改变成我们需要的了!

useradd设定了默认值,可以方便的快速创建新用户.调用useradd会对下面👇的系统文件进行变更:

  • 在 /etc/passwd 里面创建一行与账号相关的数据,包括创建 UID/GID/家目录等;
  • 在 /etc/shadow 里面将此账号的口令相关参数填入,但是尚未有口令;
  • 在 /etc/group 里面加入一个与账号名称一模一样的组名;
  • 在 /home 底下创建一个与账号同名的目录作为用户家目录,且权限为 700

可以通过下面👇的命令查看 useradd的默认值:

1
2
3
4
5
6
7
8
[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)

useradd默认值保存在/etc/default/useradd中.

passwd

passwd用来创建和修改用户的口令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
[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. <==竟然还是成功修改了!

范例二:用 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还可以用来锁定账户

1
2
3
4
5
6
7
8
9
10
11
12
[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::
# 口令字段恢复正常!

快速创建一个用户并设置密码的脚本:

1
2
adduser "$1"
echo "$2" | passwd "$1" --stdin

chpasswd

chpasswd命令是批量更新用户口令的工具,是把一个文件内容重新定向添加到/etc/shadow中。

先创建用户密码对应文件,格式为username:password,如abc:abc123,必须以这种格式来书写,并且不能有空行,保存成文本文件user.txt,然后执行chpasswd命令:

1
chpasswd < user.txt

chage

chage命令是用来修改帐号和密码的有效期限,还可以展示账户口令详细信息.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[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

chage 有一个功能很不错喔!如果你想要让『使用者在第一次登陆时, 强制她们一定要更改口令后才能够使用系统资源』,可以利用如下的方法来处理的!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
范例二:创建一个名为 agetest 的账号,该账号第一次登陆后使用默认口令,
但必须要更改过口令后,使用新口令才能够登陆系统使用 bash 环境
[root@www ~]# useradd agetest
[root@www ~]# echo "agetest" | passwd --stdin agetest
[root@www ~]# chage -d 0 agetest
# 此时此账号的口令创建时间会被改为 1970/1/1 ,所以会有问题!

范例三:尝试以 agetest 登陆的情况
You are required to change your password immediately (root enforced)
WARNING: Your password has expired.
You must change your password now and login again!
Changing password for user agetest.
Changing password for agetest
(current) UNIX password: <==这个账号被强制要求必须要改口令!

非常有趣吧!你会发现 agetest 这个账号在第一次登陆时可以使用与账号同名的口令登陆, 但登陆时就会被要求立刻更改口令,更改口令完成后就会被踢出系统。再次登陆时就能够使用新口令登陆了!

usermod

usermod用来修改已经存在的用户配置信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
[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 口令栏的 ! 拿掉,解冻啦!

范例一:修改使用者 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

userdel命令用于删除给定的用户,以及与用户相关的文件。若不加选项,则仅删除用户帐号,而不删除相关文件。

1
2
3
4
5
6
7
8

[root@www ~]# userdel [-r] username
选项与参数:
-f:强制删除用户,即使用户当前已登录;
-r:连同用户的家目录也一起删除

范例一:删除 vbird2 ,连同家目录一起删除
[root@www ~]# userdel -r vbird2

finger

finger命令用于查找并显示用户信息

1
2
3
4
5
6
7
8
9
10
11
12
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.

列出的信息说明如下:

  • Login:为使用者账号,亦即 /etc/passwd 内的第一字段;
  • Name:为全名,亦即 /etc/passwd 内的第五字段(或称为批注);
  • Directory:就是家目录了;
  • Shell:就是使用的 Shell 文件所在;
  • Never logged in.:figner 还会调查用户登陆主机的情况喔!
  • No mail.:调查 /var/spool/mail 当中的信箱数据;
  • No Plan.:调查 ~vbird1/.plan 文件,并将该文件取出来说明!

不过是否能够查阅到 Mail 与 Plan 则与权限有关了!因为 Mail / Plan 都是与使用者自己的权限配置有关, root 当然可以查阅到用户的这些信息.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
范例二:利用 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

chfn

chfn命令用来改变finger命令显示的信息。这些信息都存放在/etc目录里的passwd文件里。若不指定任何选项,则chfn命令会进入问答式界面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[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 所修改出来的!

chsh

chsh命令用来更换登录系统时使用的shell。若不指定任何参数与用户名称,则chsh会以应答的方式进行设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
[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

id

id命令可以显示真实有效的用户ID(UID)和组ID(GID)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@www ~]# id [username]
-g或--group   显示用户所属群组的ID。
-G或--groups 显示用户所属附加群组的ID。
-n或--name   显示用户,所属群组或附加群组的名称。
-r或--real   显示实际ID。
-u或--user   显示用户ID。
-help   显示帮助。
-version   显示版本信息。

范例一:查阅 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 这个命令也可以用来判断系统上面有无某账号!

群管理

groupadd

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

1
2
3
4
5
6
7
8
9
10
11
[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

groupmod命令更改群组识别码或名称。

1
2
3
4
5
6
7
8
9
10
[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:!::

groupdel

groupdel命令用于删除指定的工作组

1
2
3
4
5
6
7
8
[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 ,那可是会造成很大的困扰的!

gpasswd

gpasswd用来管理群组的命令,它可以用来创建群组管理员.并可以将用户加入或移除群组.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 关于系统管理员(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

ACL

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

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

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

由于 ACL 是传统的 Unix-like 操作系统权限的额外支持项目,因此要使用 ACL 必须要有文件系统的支持才行。目前绝大部分的文件系统都有支持 ACL 的功能,包括 ReiserFS, EXT2/EXT3, JFS, XFS 等等。在我们的 CentOS 5.x 当中,默认使用 Ext3 是启动 ACL 支持的!至于察看你的文件系统是否支持 ACL 可以这样看:

1
2
3
4
5
6
7
8
[root@www ~]# mount  <==直接查阅挂载参数的功能
/dev/hda2 on / type ext3 (rw)
/dev/hda3 on /home type ext3 (rw)

[root@www ~]# dumpe2fs -h /dev/hda2 <==由 superblock 内容去查询
....(前面省略)....
Default mount options: user_xattr acl
....(后面省略)....

由 mount 单纯去查阅不见得可以看到实际的项目,由于目前新的 distributions 常常会主动加入某些默认功能, 如上表所示,其实 CentOS 5.x 在默认的情况下 (Default mount options:) 就帮你加入 acl 的支持了! 那如果你的系统默认不会帮你加上 acl 的支持呢?那你可以这样做:

1
2
3
4
5
6
7
[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

setfacl

setfacl 配置某个目录/文件的 ACL 规范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[root@www ~]# setfacl [-bkRd] [{-m|-x} acl参数] 目标文件名
选项与参数:
-m :配置后续的 acl 参数给文件使用,不可与 -x 合用;
-x :删除后续的 acl 参数,不可与 -m 合用;
-b :移除所有的 ACL 配置参数;
-k :移除默认的 ACL 参数,关于所谓的『默认』参数于后续范例中介绍;
-R :递归配置 acl ,亦即包括次目录都会被配置起来;
-d :配置『默认 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[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 配置吧!

1
2
3
4
5
6
7
8
9
10
11
12
13
# 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)』 我们举个例子来看,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 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--

常用命令

su

su命令用于切换当前用户身份到其他用户身份,变更时须输入所要变更的用户帐号与密码。

1
2
3
4
5
6
7
[root@www ~]# su [-lm] [-c 命令] [username]
选项与参数:
- :单纯使用 - 如『 su - 』代表使用 login-shell 的变量文件读取方式来登陆系统;
若使用者名称没有加上去,则代表切换为 root 的身份。
-l :与 - 类似,但后面需要加欲切换的使用者账号!也是 login-shell 的方式。
-m :-m 与 -p 是一样的,表示『使用目前的环境配置,而不读取新使用者的配置文件』
-c :仅进行一次命令,所以 -c 后面可以加上命令喔!

w/who

wwho用来查看当前主机登录的用户.

1
2
3
4
5
6
7
8
9
10
11
12
[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)

账户管理例子

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

账号名称 账号全名 支持次要群组 是否可登陆主机 口令
myuser1 1st user mygroup1 可以 password
myuser2 2nd user mygroup1 可以 password
myuser3 3rd user 无额外支持 不可以 password
1
2
3
4
5
6
7
8
9
10
11

# 先处理账号相关属性的数据:
[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 myuser32

任务二:我的使用者 pro1, pro2, pro3 是同一个项目计划的开发人员,我想要让这三个用户在同一个目录底下工作, 但这三个用户还是拥有自己的家目录与基本的私有群组。假设我要让这个项目计划在 /srv/projecta 目录下开发, 可以如何进行?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 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