跳到主要内容

用户组管理

前言

用户组在 Linux 系统上发挥着重要作用。最主要的功能就是为选定的用户提供一种相互共享文件的方法。更重要的是系统管理员可以更有效地管理用户权限,因为他们可以将权限分配给组而不是个人用户。

一个用户组下可以包含多个用户,同样的一个用户也可以有多个用户组。比如一个公司有很多人,但是这些人通常会分为不同的部门,而每个部门都有各自的功能职责。这里我们就可以将每个部门对应的职责理解为权限,公司地人虽然很多但是分部门管理对公司而言就简单很多。

用户组也是一个道理,Linux 的文件系统就是一个权限系统,而通过用户组就可以很轻易的实现多个用户文件共享。

另外,用户组的应用虽然很简单,但是涉及到用户的概念,因此还是推荐你先看下 用户管理 之后再回过头来看下面的内容会发现简单很多。

同样的,关于文件的权限以及所有者、所属组的问题这里也不做赘述,可以参考下 chown 命令与文件归属系统chmod 命令与文件权限系统 章节内容。

创建组(groupadd 命令)

创建组的命令是 groupadd,它的语法特别简单:

groupadd [options] GROUP_NAME

groupadd 命令有几个可选参数,不过在实际使用中很少使用。主要可选参数如下:

-f, --force               强制执行(抑制不必要信息)
-g, --gid GID 指定组ID

-r, --system 创建为系统组

-o, --non-unique 允许组ID重复(不推荐使用, 不做介绍)
-p, --password PASSWORD 为组指定安全密码(不推荐使用, 不做介绍)

下面就具体说下~

注意

groupadd 命令只有 root 用户或者具有 sudo 权限的用户才能使用。

创建普通组

想在系统中创建一个组特别简单,主要要在 groupadd 命令后面跟上具体的组名即可,示例:

$ sudo groupadd example_group

命令顺利执行就表示组创建成功了,我们可以看下 /etc/group 文件该组的信息:

$ sudo grep example /etc/group
example_group:x:1001:

注意看,该组的 id 是 1001,是由系统自动分配的。

强制创建组(不推荐)

如果现在再重复创建组会怎样呢?看下输出:

$ sudo groupadd example_group
groupadd: group 'example_group' already exists

结果显而易见,提示组已存在。如果不想看到该输出信息我们可以指定 -f 参数:

$ sudo groupadd -f example_group

$ sudo grep example /etc/group
example_group:x:1001

实际上,-f 参数没有其他作用,仅仅是用于抑制信息输出,并不能真的做到强制执行。

指定GID(不推荐)

前面创建的组的ID都是由系统自动分配:

$ sudo grep example /etc/group
example_group:x:1001:
[---]
+-----------> 系统自动分配的组ID

实际上,我们也可以使用 -g 参数指定组的ID,但是一般不推荐使用。看下示例:

$ sudo groupadd -g 2000 explicit_group

$ sudo grep explicit /etc/group
explicit_group:x:2000:
[---]
+----------> 显示设置的组ID

不过在实际上似乎没啥卵用。啥?你说你想要个靓号 666、888?

创建为系统组(不推荐)

前面示例中的组其实都是系统中的普通组,这个可以从 GID 中可以看出来。与 UID(用户ID)一样,在 Linux 系统中 组ID(GID) 同样也是采用无符号整形数据类型。

GID 是用户组的唯一标识,当你创建一个组时默认会分配一个 GID。而且在实际使用中,GID 与组名是等效的。

现代计算机 GID 理论上的可分配的范围是:0<GIDrange<2320 < GID_{range} < 2^{32},但实际上不同的 Linux 发行版都会对允许分配的 GID 做一定的限制。这些限制被定义在 /etc/login.defs 配置文件中,比如我当前的操作系统:

$ sudo grep GID /etc/login.defs
GID_MIN 1000
GID_MAX 60000
#SYS_GID_MIN 100
#SYS_GID_MAX 999

这个是默认配置,实际上是可以修改的。同时也就是说,默认情况下普通组的 GID 取值范围是 1000<GIDrange<600001000 < GID_{range} < 60000

另外,注意最后还有两行以 # 注释的配置,这两个配置就是用于指定系统级别的组的 GID 取值范围,范围通常是 100<GIDrange<999100 < GID_{range} < 999

与用户组和系统用户组不同,普通组与系统组其实没什么区别,不存在过期问题。系统组其实就是用于保留使用,通常是保留给系统级别软件自动创建的组使用。

创建系统组只需要指定 -r 参数即可,示例:

$ sudo groupadd -r sys_group

$ sudo grep sys_group /etc/group
sys_group:x:998:

注意看新建的这个组的 GID,实际上并没有任何用,与普通组没有任何区别,因此并不推荐使用。

修改组(groupmod 命令)

想一下,如果想对以存在的组做微调该怎么办?比如修改 GID、修改组名。这个时候就需要 groupmod 命令了,基本语法如下:

groupmod [options] GROUP_NAME

其中,可选参数与 groupadd 完全相同,不过在实际中仅推荐使用下面两个可选参数,其他的就不要使用了:

-n, --new-name NEW_GROUP      修改组名称
-g, --gid GID 修改组 GID

修改组名称

这个在实际上用的可能是最多的,因为单身久了吗,打字免不了手抖啥的。比如在创建组时手抖啊字母打错了,这个时候就需要在组创建完成后进行修改了。

还是以前面创建的组 example_group 为例,现在我要将该组名修改为 leader_group:

$ sudo groupmod -n leader_group example_group

现在再看下组系统信息文件,就会发现原来的组 example_group 不见了,只有一个 leader_group:

$ sudo grep -E 'example|leader' /etc/group
leader_group:x:1001:

这个在实际中很实用的~

修改 GID

组的 GID 一般很少有修改的需求,不过如果你领导想要一个靓号啥的对吧,嗯,这个可能性还是会存在的。

groupadd 命令一样,只需要试用 -g 参数指定一个 GID 即可。

这回以组 explicit_group 为例,先看下组的信息:

$ sudo grep explicit_group /etc/group
explicit_group:x:2000:

现在使用 -g 参数将 GID 修改为 6666:

$ sudo groupmod -g 6666 explicit_group

现在再来看下组的 ID 信息:

$ sudo grep explicit_group /etc/group
explicit_group:x:6666:

删除组(groupdel 命令)

当某个 普通组 不再需要时就可以将该组删掉。注意,并不会将组内的成员一并删除。

语法如下:

groupdel [-f] GROUP_NAME

现在来看下:

删除普通组

在此之前先创建一个用户和一个组:

$ sudo useradd web_user
$ sudo groupadd demo_group

之后将用户 web_user 添加到组 demo_group 中:

$ sudo groupmems -g demo_group -a web_user

现在来看下用户信息:

$ id web_user
uid=1001(web_user) gid=1001(web_user) groups=1001(web_user),6667(demo_group)

此时用于 web_user 就有了两个组,一个是同名的主要组 web_user,另一个就是我们刚刚创建的普通组 demo_group。

现在来将组 demo_group 删掉:

$ sudo groupdel demo_group

再次看下用户信息和组文件信息:

$ id web_user
uid=1001(web_user) gid=1001(web_user) groups=1001(web_user)

$ sudo grep demo_group /etc/group

可以看到组已经不存在了~

强制删除组/删除主要组

在前面,我们删的是是普通组。如果我想要删除用户 web_user 同名的主要组该怎么办?来看下:

$ sudo groupdel web_user
groupdel: cannot remove the primary group of user 'web_user

你看,删除失败,并提示无法删除用户的主要组。实际上是不建议直接删除用户的主要组的,因为通常情况下当用户被删掉之后同名的主要组会自动被删除(前提是你没做定制化设置)。

如果真的要删除用户的主要组只需要加上 -f 参数即可。该参数表示强制执行。

示例:

$ sudo groupdel -f web_user

$ sudo cat /etc/group | grep web_user

这会用户的主要组真的被删除了。但是有个问题,如果此时看用户的信息你就会发现:

$ id web_user
uid=1001(web_user) gid=1001 groups=1001

是的,主要组确实被删除了,但是 gid 的指向还是存在的,但实际上该 gid 在系统中也不存在(至于为什么会这样,触碰到盲区了,这个可能就是祖师爷特别的考量才这么设计的吧)。

现在我们来考虑另一个问题,因为用户信息依然保留着主要组的 GID(虽然组已不存在),也就是说如果我们此时创建一个组并将组的 GID 设置为用户的 GID 1001 会怎样?

来看下:

$ sudo groupadd -g 1001 pri_group

再来看下用户的信息:

$ id web_user
uid=1001(web_user) gid=1001(pri_group) groups=1001(pri_group)

好吧,此时就暴露了强制删除用户的主要组的问题了。所以,在实际工作中,除非你有能令人信服的理由,否者千万别强制删除用户的主要组!!!!

组成员管理(groupmems 命令)

用户组创建完成之后就涉及到如果管理组内的成员了,比如添加、删除等等。具体见:组成员管理命令 groupmems