Linux用户管理与权限那些事

669 阅读11分钟

1. 前言

嗨咯,大家好我是小火柴。今天主要是想和大家分享一篇我学习Linux用户管理与权限的故事,文章难度不是很深(Linux老手或大佬求放过😄),主要是记录一下我使用Linux过程中遇到的一些问题并且总结下来,文章若有纰漏,望诸君海涵与指正。

最早开始上手Linux时,是在学习CI/CD的时候,在Linux系统中使用Docker部署Jenkins服务来实现自动化的过程(有兴趣的朋友可以看看我这篇Jenkins+Docker实现部署你的Vue应用文章哦),我经常会看到类似“permissions denied”这样的错误:

当然,网上一搜全是说要加权限,比如这样:

sudo chmod 777 -R /home/jenkins_data

又或者这样:

sudo chown -R 1000:1000 /home/jenkins_data

好用是好用了,但是我就是很好奇这个 777 是啥意思为什么不能是 888 ? 为什么不能是英文 ?

此外使用ls命令查看文件时经常看到这样的一大串:

对于一个像我这样的Linux新手来说确实特别懵逼,而且很多时候对于无法使用的命令或操作经常要借助sudo临时借用root身份去解决问题,我觉得不是特别安全,而且也不够重视Linux的权限问题。于是我带着这样的疑问,开始寻找这些问题的答案,首先要说的就是Linux的多用户系统。以下操作都在CentOS 7中测试,其他系统大同小异。

2. 用户/用户组的概念及管理

Linux系统是一个多用户多任务的分时操作系统(Unix),可以理解为同一时间可以有不同用户使用同一操作系统干不同的事情。这些用户可不是同一类人,有的是超级大管家(root),有的是普通小市民(test),它们虽然共同住在一起,但是有些东西并不是普通小市民可以用的,有时候要用还需要临时借用一下sudo命令使用管家的权限。可是能力越大,责任就越大,超级大管家哪一天想不开使用了rm -rf /*,那么恭喜直接牢底坐穿🙃。小市民虽然普通但是遵纪守法绝不会干出格的事情。而正是这样职责明确的系统才让Linux无比强大,这也是我特别喜欢Linux的原因之一啦哈哈。不扯了不扯了,我们进入主题:如何管理用户呢?

2.1 创建新用户

我们最初是有一个root用户默认存在的,它无比强大,但是大家如果和我一样是初学者最好创建一个普通用户来学习,而且最好是在虚拟机中搞,大不了删掉重来嘛~

# 创建一个普通用户(先用root用户登录)
# 可以使用`-g`分配用户组,为了演示groupadd先不加了
useradd foo

# 修改密码
passwd foo

# 切换用户
su foo

此时我们去home目录下可以看到多了一个文件foo

我们可以看到有很多列,但是我们目前只需要关注三列,最左边的(drwx------)是文件/文件夹 的读写或执行权限,中间两个foo一个是目录所有者和目录所有者所在的群组,我们先来说说用户用户组是啥意思。

2.2 用户/用户组和uid/gid

假如我们有一个开发部门,部门里面有前端组、测试组、后端组、UI组等小组,而每一个组都具有做一些事情的权利,前端组主要负责开发页面啦、小程序啦、基础组件开发等等,其他组也是类似的,那这些成员就类似于Linux中的用户,而前端组就是用户组,虽然本身这个用户而言它不一定有其他用户的权限,但一定有用户组的权限。

另外每一个用户和所在的组都会有一个唯一的编号来区分其他用户和用户组,这个编号十分重要,就像身份证ID一样。Linux内核可不是根据用户名/用户组名来确定权限的,而是根据uid/gid来区分的。uid 和 gid 由 Linux 内核负责管理,并通过内核级别的系统调用来决定是否应该为某个请求授予特权。比如当进程试图写入文件时,内核会检查创建进程的 uid 和 gid,以确定它是否有足够的权限修改文件。我在学习Docker时常就很困惑容器的用户和宿主机的用户有什么区别,但是理解了uid和gid之后就明白了。

我们可以使用whoamigroupsid命令查看当前用户/用户所在组和uid/gid:

2.3 用户组的管理

我们创建foo时,如果不分配它所在群组,那么它的用户组默认就是foo,我们可以使用groups命令查看当前用户的群组:

[foo@localhost home]$ groups
foo

那如果我想变更foo的群组呢,原本他搞前端现在想做后端了,这个也是没有问题滴,我们首先要有这个“后端组”嘛,我们先添加一个api组,它的命令和添加用户很类似:

# 先切换到root
su -

# 添加群组api
groupadd api

# 给foo用户分配群组 -g 是修改用户群组的意思
usermod -g api foo

然后我们发现此时foo这个用户所在组从foo变成了api

usermod其实就是user+modify的缩写,它是用来修改用户的一个很重要的命令,它必须要在root下运行,后面要介绍的chown也是如此。

现在foo这个小伙子进了api组后总是抱怨自己就是写API的,他又想多加一个front组来写前端,那按上面的步骤再整嘛,不过我们可以这样做,一次性就可以添加多个群组了:

usermod -G api,front foo

但是不管使用-g还是-G参数都会将原来的群组给干掉,如果要保留原来的群组需要加上-a参数,而且这个参数只能与-G一起使用。

注意,很多像我一样刚学Linux系统的朋友,刚开始发现很多命令都会没有权限这很正常,网上也会告诉我们在suders文件中给我们一个使用sudo命令的权限,但是用久了跟使用root没差别的,所以建议刚开始就不要这样弄,现在虽然麻烦了点,但是方便理解它的权限控制系统。

3. 文件权限管理

我们知道了用户与用户群组的概念后,下面进入一个十分重要的环节:文件权限。

我们在文章的开头有一个图片:

第一列这么一大串是个什么玩意?

我们先了解一下那些小写的英文字母代表什么吧:

  • d(directory):说明当前是一个文件夹
  • l(link):说明是一个链接
  • r(read):说明文件可读
  • w(write):说明文件可写,当然也可以被删除
  • x(execute ):可以运行该文件

我们可以看到有很多重复的出现,并且串在一起很难看懂,不过我们有了上面的铺垫后就很容易理解啦~

首先-代表一个坑位,如果没有任何英文字母的情况会有10个坑位,最后一个.代表结束,第一个坑位可以是ld-分别表示当前是一个链接、目录、文件,而后面每三个一组代表文件所有者、群组用户、其他用户的权限。用一张画得比较丑的图来看看(没错我画的):

下面我们来看看如何分配权限吧。

3.1 使用数字表示权限

使用数字分配权限比较方便和常用,wrx分别对应421,分配权限的时候只需要把对应的数字加起来就可以了,我们先创建一个test.txt 文件并写入'hello':

echo 'hello' > test.txt

此时的文件权限是644

那么我们现在给这个文件分配760权限(为了演示),也就是群组可读可写,其他用户任何权限,我们使用chmod这个命令来分配:

chmod 760 test.txt

此时我们用ll命令来查看:

可见,权限成功分配成功了,是不是很开心呢~我们再用图来看看:

我们经常看到的777其实就是所有用户都有读写可执行权限,其他的大家可以自己推算出来。我们经常看到用sudo去执行这个chmod命令,其实没必要的,给文件分配权限只有两种可能,一个是文件的所有者,另外一个是root,可以理解我们在foo自个儿的家里玩,想咋整就咋整咯。除了用数字来表示权限,还有一种是用字母表示。

3.2 用字母分配权限

我们一般会用下面三个符号来分配权限:

  • +:增加某个权限
  • -:移除某个权限
  • =:分配某个权限

ugo来表示当前用户、用户组、其他用户,我们来看几个例子就明白啦~

#文件 test.txt 的所有者增加读和运行的权限。
chmod u+rx test.txt

#文件 test.txt 的群组其他用户增加读的权限。
chmod g+r test.txt 

#文件 test.txt 的其他用户移除读的权限。
chmod o-r test.txt 

#文件 test.txt 的群组其他用户增加读的权限,其他用户移除读的权限。
chmod g+r o-r test.txt 

#文件 test.txt 的群组其他用户和其他用户均移除读的权限。
chmod go-r test.txt 

#文件 test.txt 的所有用户增加运行的权限。
chmod +x test.txt 

#文件 test.txt 的所有者分配读,写和执行的权限;
#群组其他用户分配读的权限,不能写或执行;
#其他用户没有任何权限。
chmod u=rwx,g=r,o=- test.txt 

用字母其实也比较方便,虽然看起来有点复杂,但是至少不用自己算。不过我个人喜欢上面的数字,这个看大家喜好啦~如果我们要递归分配一个目录下所有文件,不管是哪种方式加上-R参数即可。

3.3 改变文件所有者与群组

对于那些想使用其他用户甚至是root文件的用户,或者把自己的文件“转让”给其他用户时,那么就必须向“超级大管家”root来通告一声啦,他会使用chown来帮我们,假设此时还有一个bar用户(来自ui组),我们把刚刚创建的test.txt文件让给他:

chown bar:ui test.txt

此时bar心中狂喜,这下foo肯定操作不了啦,此时foo就像啥也没发现一样直接使用rm删掉了,咦?我们是不是漏掉了啥?此时我们退到home,虽然子目录权限变更了,但是父级目录的权限还是foo的呀,那如何让foo彻底失去控制呢?我们直接使用-R递归文件目录:

chown -R bar:ui /home/foo

就好像把房子卖给了bar,此时别说使用cat查看了,就连cd命令都进不去了:

好家伙的,这下次房子都卖了,门都不让进了,有啥办法没,好歹让可怜的foo进个门啊,text.txt文件还是自己创建的呢!当然可以,我们学习了chownchmod后可以结合一起用呀,大家可以自己尝试一下呦~(小提示:先使用usermod改变群组,再使用chmod添加文件权限)

4. 总结

文章终于写完了,有点如释重负的感觉,一点点好奇心才有了这篇文章。我这篇文章主要讲了以下几个重点:

  • 用户/用户组以及uidgid的的概念,包括groupadduseraddusermod的使用
  • 文件的权限,如何使用数字和字母表示权限
  • 如何管理权限,通过使用chownchmod来合理分配权限

我是一个搞前端开发的人,而且平时大部分时间也没有花在Linux上,但是自从接触了CI/CD后我感觉我的新世界打开了,Linux学起来很枯燥,但是我还是希望通过自己这样的讲解有人会理解,我自己也通过写文章收获了很多,希望自己继续努力!

5. 参考

【1】理解 docker 容器中的 uid 和 gid