阅读 7606

一言不合就改成 777 权限?会出人命的!

最近和几个朋友开发项目,期间使用了一台服务器跑模型,这台服务器是多人公用的,很多人都在上面有自己的账号,互不干涉内政,一切看起来十分井然有序。

近期,这个服务器上刚挂载了一块新硬盘,是一位朋友使用 root 账号挂载的,然后将磁盘映射到某个文件夹下。然而挂载好了之后发现使用普通账号没有权限在文件夹下操作,无法创建文件,于是他干脆就直接把文件夹权限改成 777 了。我心想,这还了得,改成 777 了,其他人在里面乱改咋办?会出人命的!

所以,我就这件事详细梳理了一下 Linux 下的用户、用户组、文件权限等基本知识,看完这些,以后不要动不动就把文件夹改成 777 权限了。

基本操作

首选我们梳理一下 Linux 下的用户、用户组、文件权限等基本知识,然后后面通过一个案例来实际演示一下权限设置的一些操作。

首先 Linux 系统中,是有用户和用户组的概念的,用户就是身份的象征,我们必须以某一个用户身份来操作一个系统,实际上这就对应着我们登录系统时的账号。而用户组就是一些用户的集合,我们可以通过用户组来划分和统一管理某些用户。

比如我要在微信发一条朋友圈,我只想给我的亲人们看,难道我发的时候还要一个个去勾选所有的人?这未免太麻烦了。为了解决这问题,微信里面就有了标签的概念,我们可以提前给好友以标签的方式分类,发的时候直接勾选某个标签就好了,简单高效。实际上这就是用户组的概念,我们可以将某些人进行分组和归类,到时候只需要指定类别或组别就可以了,而不用一个个人去对号入座,从而节省了大量时间。

在 Linux 中,一个用户是可以属于多个组的,一个组也是可以包含多个用户的,下面我以一台 Ubuntu Linux 为例来演示一下相关的命令和操作。

用户和用户组

首先查看所有用户,命令如下:

cut -d':' -f 1 /etc/passwd
复制代码

结果:

root
daemon
bin
sys
...
ubuntu
mysql
复制代码

这里一行就是一个用户名,由于太多,部分就省略了,实际上这个命令就是从密码文件中把用户名单独列出来了。

然后查看所有用户组,命令也是类似的:

cut -d':' -f 1 /etc/group
复制代码

结果:

root
daemon
bin
sys
...
ubuntu
mysql
复制代码

结果基本是类似的,因为每个用户在被创建的时候都会自动创建一个同名的组作为其默认的用户组。

这里我是使用 ubuntu 这个账号来登录的,下面我来看下 ubuntu 这个账号是属于哪些组。

查看一个用户所属组的命令格式如下:

gorups <username>
复制代码

这里就是 groups 命令加上用户名就能查看该用户名所属的组了,如果不加用户名的话就默认是当前用户。

例如查看 ubuntu 这个用户所属于的组,命令如下:

groups ubuntu
复制代码

结果:

ubuntu : ubuntu adm cdrom sudo dip plugdev lxd lpadmin sambashare
复制代码

还不少,这个用户被分配到了很多组下,比如同名的组 ubuntu,还有 sudo 组,另外还有一些其他的组。

其中 sudo 组比较特殊,如果被分到了这个组里面就代表该账号拥有 root 权限,可以使用 sudo 命令。

了解了怎样查看用户所属的组,我们也应该反过来了解如何查看一个用户组里面包含哪些用户啊。

查看某个用户组下所有用户命令如下:

members <group>
复制代码

不过这个命令不是自带的,需要额外安装 members 包,命令如下:

sudo apt-get install members
复制代码

例如查看 sudo 用户组下的所有用户,即拥有 root 权限的用户:

members sudo
复制代码

结果:

ubuntu hadoop
复制代码

可以看到拥有 root 权限的用户有两个,ubuntu 和 hadoop,当然不同的机器结果肯定是不一样的。

接下来介绍一个比较有用的命令,就是 id 命令,它可以用来查看用户的所属组别,格式如下:

id <username>
复制代码

例如查看 ubuntu 用户的信息,就是这样:

id ubuntu
复制代码

结果:

uid=500(ubuntu) gid=500(ubuntu) groups=500(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare)
复制代码

这里有一个 gid,作为主工作组,后面还有个 groups,它列出了用户所在的所有组。主工作组只有一个,而后者的数量则不限。可以看到用户组的结果和使用 groups 命令看到的结果是一致的。

接下来我们再来了解一下如何创建一个用户和怎样为用户分配组别。

添加一个用户命令格式如下:

sudo adduser <username>
复制代码

比如我要添加一个用户 cqc,命令就可以这么写:

sudo adduser cqc
复制代码

这里使用的命令前面都带有 sudo,因为毕竟是系统级别的操作。

添加一个组的命令格式如下:

sudo groupadd <group>
复制代码

格式是类似的,后面跟一个组的名称就可以了,例如我要为我的实验室创建一个用户组,那么就可以使用如下命令:

sudo groupadd lab
复制代码

创建完了用户和组,那得把它们关联起来吧,关联的意思就是把某个用户加入到某个组里面,命令格式如下:

sudo adduser <username> <group>
复制代码

或者使用 usermod 命令:

sudo usermod -G <group> <username>
复制代码

如果要添加多个组的话,可以通过 -a 选项指定多个名称:

sudo usermod -aG <group1,group2,group3..> <username>
复制代码

例如我要将 cqc 用户添加到 sudo 用户组中,命令就是:

sudo adduser cqc sudo
复制代码

或:

sudo usermod -G sudo cqc
复制代码

这样就为用户和用户组做好关联了。

文件权限管理

了解了这些之后,我们再来了解一下文件权限的相关知识,下面我们先随便找一个目录,查看一下文件的列表。

列出某个目录下文件详细信息的命令如下:

ll
复制代码

或者使用:

ls -l
复制代码

比如我这里列出了 /etc/nginx 目录下的文件列表:

total 80
drwxr-xr-x   7 root root  4096 Jun 21 22:16 ./
drwxr-xr-x 103 root root  4096 Sep  4 18:04 ../
drwxr-xr-x   2 root root  4096 Jul 12  2017 conf.d/
-rw-r--r--   1 root root  1077 Feb 12  2017 fastcgi.conf
-rw-r--r--   1 root root  1007 Feb 12  2017 fastcgi_params
-rw-r--r--   1 root root  2837 Feb 12  2017 koi-utf
-rw-r--r--   1 root root  2223 Feb 12  2017 koi-win
-rw-r--r--   1 root root  3957 Feb 12  2017 mime.types
-rw-r--r--   1 root root  1505 Jun 21 20:24 nginx.conf
-rw-r--r--   1 root root 12288 Jun 21 20:44 .nginx.conf.swp
-rw-r--r--   1 root root   180 Feb 12  2017 proxy_params
-rw-r--r--   1 root root   636 Feb 12  2017 scgi_params
drwxr-xr-x   2 root root  4096 Jun 21 22:42 sites-available/
drwxr-xr-x   2 root root  4096 Jun 21 19:08 sites-enabled/
drwxr-xr-x   2 root root  4096 Jun 21 19:08 snippets/
-rw-r--r--   1 root root   664 Feb 12  2017 uwsgi_params
drwxr-xr-x   2 root root  4096 Jun 22 02:44 vhosts/
-rw-r--r--   1 root root  3071 Feb 12  2017 win-utf
复制代码

我们注意到了每一行都是一个文件或文件夹的信息,一共包括七列:

  • 第一列是文件的权限信息

  • 第二列表示该文件夹连接的文件数

  • 第三列表示文件所属用户

  • 第四列表示文件所属用户组

  • 第五列表示文件大小(字节)

  • 第六列表示最后修改日期

  • 第七列表示文件名

其中第一列的文件权限信息是非常重要的,它由十个字符组成:

  • 第一个字符代表文件的类型,有三种,- 代表这是一个文件,d 代表这是一个文件夹,l 代表这是一个链接。

  • 第 2-4 个字符代表文件所有者对该文件的权限,r 就是读,w 就是写,x 就是执行,如果是文件夹的话,执行就意味着查看文件夹下的内容,例如 rw- 就代表文件所有者可以对该文件进行读取和写入。

  • 第 5-7 个字符代表文件所属组对该文件的权限,含义是一样的,如 r-x 就代表该文件所属组内的所有用户对该文件有读取和执行的权限。

  • 第 8-10 个字符代表是其他用户对该文件的权限,含义也是一样的,如 r-- 就代表非所有者,非用户组的用户只拥有对该文件的读取权限。

我们可以使用 chmod 命令来改变文件或目录的权限,有这么几种用法。

一种是数字权限命名,rwx 对应一个二进制数字,如 101 就代表拥有读取和执行的权限,而转为十进制的话,r 就代表 4,w 就代表 2,x 就代表 1,然后三个数字加起来就和二进制数字对应起来了。如 7=4+2+1,这就对应着 rwx;5=4+1,这就对应着 r-x。所以,相应地 777 就代表了 rwxrwxrwx,即所有者、所属用户组、其他用户对该文件都拥有读取、写入、执行的权限,这是相当危险的!

赋予权限的命令如下:

sudo chmod <permission> <file>
复制代码

例如我要为一个 file.txt 赋予 777 权限,就写成:

sudo chmod 777 file.txt
复制代码

另外我们也可以使用代号来赋予权限,代号有 u、g、o、a 四中,分别代表所有者权限,用户组权限,其他用户权限和所有用户权限,这些代号后面通过 + 和 - 符号来控制权限的添加和移除,再后面跟上权限类型就好,例如:

sudo chmod u-x file.txt
复制代码

就是给所有者移除 x 权限,也就是执行权限。

sudo chmod g+w file.txt
复制代码

就是为用户组添加 w 权限,即写入权限。

另外如果是文件夹的话还可以对文件夹进行递归赋权限操作,如:

sudo chmod -R 777 share
复制代码

就是将 share 文件夹和其内所有内容都赋予 777 权限。

好,有了权限的标识,那我们还得把用户和用户组与文件关联起来啊,这里使用的命令就是 chown 和 chgrp 命令。

命令格式如下:

sudo chown <username> <file>
sudo chgrp <group> <file>
复制代码

例如我要将 file.txt 的所有者换成 cqc,那就可以使用如下命令:

sudo chown cqc file.txt
复制代码

如果我要将 file.txt 所属用户组换成 lab,那就可以使用如下命令:

sudo chgrp lab file.txt
复制代码

另外同样可以使用 -R 来进行递归操作,如将 share 文件夹及其内所有内容的所有者都换成 cqc,命令如下:

sudo chown -R cqc share/
复制代码

好,了解了 chown、chgrp、chmod 之后,我们就可以灵活地对文件权限进行控制了。

实战演示

可能上面说起来有点抽象,下面我们以一个实例来演示一下权限控制的流程,通过这个流程,相信理解以上的命令都不在话下了。

首先情况是这样的,我要在某台主机上共享一些文件给我实验室的人,但这台主机上还有其他非实验室的人在使用,我只想让实验室的人查看和修改这些文件,其他人不行。

另外我自己的账号要有最高权限来管理这些文件的共享权限,即要有 root 权限。

现在我已经登录了一个 ubuntu 的账号,是系统初始化的,拥有 root 权限。

下面我就模拟创建三个账号和一个用户组,来得到如下效果:

  • 账号 cqc 是我自己使用的账号,拥有最高权限,可以自由调整文件权限信息,可以自由为某个用户分配用户组。

  • 账号 lbd 是我实验室的人员,没有 root 权限,但能查看和修改我共享的文件。

  • 账号 slb 不是我实验室的人员,没有 root 权限,也不能修改我共享的文件。

创建自己的账户

首先我先为自己创建一个账户,添加一个 cqc 的用户:

sudo adduser cqc
复制代码

运行之后会提示输入密码和其他信息:

Adding user `cqc' ...
Adding new group `cqc' (1002) ...
Adding new user `cqc' (1002) with group `cqc' ...
Creating home directory `/home/cqc' ...
Copying files from `/etc/skel' ...
Enter new UNIX password: 
Retype new UNIX password: 
passwd: password updated successfully
Changing the user information for cqc
Enter the new value, or press ENTER for the default
        Full Name []: 
        Room Number []: 
        Work Phone []: 
        Home Phone []: 
        Other []: 
Is the information correct? [Y/n] 
复制代码

这时候发现一个同名的组就被创建了,查看下 cqc 所在的组:

groups cqc
复制代码

结果如下:

cqc : cqc
复制代码

再用 id 命令查看下信息:

id cqc
复制代码

结果如下:

uid=1002(cqc) gid=1002(cqc) groups=1002(cqc)
复制代码

可以看到当前 cqc 只属于 cqc 用户组。

接下来我们创建一个用户组,叫做 lab,来标明我的实验室,命令如下:

sudo groupadd lab
复制代码

然后查看下用户组里面的成员:

members lab
复制代码

没有任何结果,说明我们创建了一个空的组,没有任何成员。

然后我们将刚才创建的 cqc 加入到该组中,因为我自己也属于该实验室,肯定也要加进来,命令如下:

sudo adduser cqc lab
复制代码

结果:

Adding user `cqc' to group `lab' ...
Adding user cqc to group lab
Done.
复制代码

然后查看下组内成员:

members lab
复制代码

结果:

cqc
复制代码

这样 lab 组内就有了 cqc 这个用户了。

别忘了 cqc 还需要拥有 root 权限,所以我们还需要将 cqc 添加到 sudo 组内,命令如下:

sudo adduser cqc sudo
复制代码

结果:

Adding user `cqc' to group `sudo' ...
Adding user cqc to group sudo
Done.
复制代码

这样就成功加入到 sudo 组了,cqc 也就是我的账户就可以使用 sudo 命令了。

查看下用户状态:

id cqc
复制代码

结果如下:

uid=1002(cqc) gid=1002(cqc) groups=1002(cqc),27(sudo),1003(lab)
复制代码

这样 cqc 就属于三个用户组了,既是实验室成员,又拥有 root 权限。

上面的分配用户组的命令我们也可以使用 usermod 来实现:

sudo usermod -aG sudo,lab cqc
复制代码

这样就添加到多个组了。

添加实验室用户

接下来,再添加实验室的另外一个人员 lbd,然后将其添加到 lab 组中,流程是类似的,命令如下:

sudo adduser lbd
sudo adduser lbd lab
复制代码

运行完毕之后,id 命令查看其信息:

id lbd
复制代码

结果如下:

uid=1004(lbd) gid=1005(lbd) groups=1005(lbd),1003(lab)
复制代码

这样就成功创建 lbd,并将其添加到实验室 lab 组了。

添加非实验室用户

最后另外添加一个用户 slb,非实验室成员,只创建账户就好了,命令如下:

sudo adduser slb
复制代码

但是我们不把他加入 lab 组中。

查看他的状态:

id slb
复制代码

结果如下:

uid=1003(slb) gid=1004(slb) groups=1004(slb)
复制代码

所以三人的状态是这样的:

id cqc
uid=1002(cqc) gid=1002(cqc) groups=1002(cqc),27(sudo),1003(lab)
id lbd
uid=1004(lbd) gid=1005(lbd) groups=1005(lbd),1003(lab)
id slb
uid=1003(slb) gid=1004(slb) groups=1004(slb)
复制代码

文件权限分配

接下来我们创建一个文件夹来共享实验室数据,放在 /srv 目录下。然后调用 mkdir 命令创建名称为 share 的文件夹,命令如下:

cd /srv
sudo mkdir share
复制代码

注意这里我还是使用 ubuntu 账户来创建的。

先看下当前目录权限:

ls -l
复制代码

结果如下:

total 12
drwxr-xr-x  3 root root 4096 Sep  4 18:17 ./
drwxr-xr-x 24 root root 4096 Sep  4 18:17 ../
drwxr-xr-x  2 root root 4096 Sep  4 18:17 share/
复制代码

可以看到 share 文件的所有者是 root,用户组也是 root,权限是 755,即只有 root 拥有修改权限,其他的只有读取和执行权限。

然后进入 share 文件夹创建一个 names.txt:

cd share
sudo vi names.txt
复制代码

编辑内容如下:

cqc
lbd
复制代码

保存完毕之后,这时查看一下文件权限,如下:

-rw-r----- 1 root root    8 Sep  4 20:00 names.txt
复制代码

权限是 640,这表明只有所有者 root 拥有写入的权限,所在组 其 组只有读的权限。

这时开启另外一个终端,登录 cqc 账号,实际上是不能查看和修改任何该文件的内容的,下面的修改和读取命令都会提示权限不够:

vi names.txt
cat names.txt
复制代码

为什么呢?因为该文件是刚才由 ubuntu 账号使用 sudo 命令创建的,因此文件的所有者是 root,并不是 cqc,因此即使文件的权限是 640,那也就不能使用文件所有者的权限,而且 cqc 也不属于 root 组,所以也不能使用文件组的权限了,因此什么都看不了,什么都改不了。

但 cqc 属于 sudo 组啊,可以利用 sudo 命令临时获取 root 权限,临时以 root 的身份来操作该文件,这样就可以来查看和修改文件了,因此下面的命令是有效的:

sudo vi names.txt
sudo cat names.txt
复制代码

但这样还是需要使用 sudo 才能修改,很不方便。

这时如果我们把文件的所有者改成 cqc,情况那就不一样了。

使用 ubuntu 账号,对 names.txt 更改其所有者为 cqc,改的命令如下:

sudo chown cqc names.txt
复制代码

这时查看下文件信息:

-rw-r----- 1 cqc  root    8 Sep  4 20:29 names.txt
复制代码

可以看到所有者信息已经变成了 cqc,这样 cqc 账号再直接查看和修改,那就可以了,不再需要 sudo 命令:

vi names.txt
cat names.txt
复制代码

这样就不会有权限提示,当然加上 sudo 更是没问题。

好,接下来 lbd 呢?我们登录试试修改。

首先当前的文件状态是这样的:

-rw-r----- 1 cqc  root    8 Sep  4 20:31 names.txt
复制代码

lbd 不是所有者了,因此前面的 rw- 权限是没什么用的,但他属于 lab 组,而该文件对于用户组的权限是 r--,也就是读取权限。

我们使用 lbd 账号来尝试看下文件的内容:

cat names.txt 
cat: names.txt: Permission denied
复制代码

很遗憾,又没有权限。因为什么?因为这个文件的用户组并不是 lab 啊,而 lbd 这个用户又不属于 root 组,所以没有任何权限。

那咋办?将文件的用户组改成 lab 就好了,使用 ubuntu 账号或 cqc 账号来操作:

sudo chgrp lab names.txt
复制代码

这样就成功将文件所属用户组改成 lab 了,接下来再使用 lbd 账号查看下文件内容:

cat names.txt
复制代码

就成功读取了。

然而 lbd 现在是没有写入权限的,因为对于用户组来说,该文件的权限是 r--,如果要获取写入权限,我们可以使用如下命令:

sudo chmod g+w names.txt
复制代码

或:

sudo chmod 660 names.txt
复制代码

这样就相当于赋予了 rw- 权限,下面我们再使用 lbd 账号尝试修改这个文件:

vi names.txt
复制代码

就没问题了。

那么对于非实验室同学 slb 呢?它没有任何权限,我们登录 slb 账号尝试修改和读取该文件:

cat names.txt
vi names.txt
复制代码

均无权限。

所以说,这样我们就成功为实验室的人员赋予了权限,而非实验室的人则没有任何权限。

如果我要为 slb 赋予读取权限咋办呢?很简单,添加一下就好了:

sudo chmod o+r names.txt
复制代码

这就是为其他用户添加了读取权限。这时 slb 就可以读取文件,但不能修改文件,也是比较安全的。

好,如果我的文件非常多呢?比如十几二十个,都放在 share 文件夹内,那不能一个个进行权限设置吧?

这时候我们只需要针对文件夹进行操作即可,下面的命令就可以为 share 文件夹赋予 775 权限,即所有者 cqc 和所在组 lab 可对其进行查看和修改,其他的人只能看不能改:

sudo chmod -R 775 share/
sudo chown -R cqc share/
sudo chgrp -R lab share/
复制代码

注意文件夹一般都会赋予 x 权限,不然连进入文件夹的权限都没有。这也就是文件夹一般会赋予 775、755,而文件会赋予 664、600、644、640 的原因了。

赋予 775 权限之后,share 的权限就变成了:

drwxrwxr-x  2 cqc  lab  4096 Sep  4 20:31 share/
复制代码

这样其他用户就只能看,不能改,这样普通文件就没什么问题了。

如文件夹内包含了可执行文件,还可以单独为其他用户针对可执行文件去除 x 权限,如去除 Python 文件的可执行权限:

sudo chmod o-x *.py
复制代码

好了,到现在为止,我们就得心应手地完成了权限控制了!

相信如果你耐心看完的话,什么用户管理、权限管理,都不在话下!



大家好,我是崔庆才,微软中国大数据工程师,在微软小冰部门。当然这是我的职业,我平时还会从事网络爬虫、Web开发、深度学习等方向的研究和开发工作。

我个人比较喜欢总结和分享,这次很荣幸在掘金的平台把自己的爬虫相关经验分享给大家,包括爬取、解析、防反爬、加速等等部分,希望大家听完之后有所收获。

本周日(10月21日)我会做客掘金Bilibili直播间为大家做一场《健壮高效的网络爬虫》的直播【网页链接】。直播中我也会抽出 5 名小伙伴赠送各赠送一本《Python3网络爬虫开发实战》书籍一本,希望大家可以支持。


关注下面的标签,发现更多相似文章
评论