Linux严格意义上来说是一个操作系统,我们称之为 “核心 (kernel)”,即Linux内核;但我们一般用户,不能直接使用kernel。而是通过kernel的“外壳”程序,也就是所谓的shell,来与kernel沟通。如何理解?为什么不能直接使用kernel? 这是因为我们一般人并不善于与 kernel(操作系统内核) 打交道,所以我们不直接使用 kernel,而是通过 kernel 的 “外壳” 程序,也就是所谓的 shell 来与 kernel 进行沟通。
从技术角度来说,shell 最简单的定义为 “命令行解释器 (command Interpreter)”,其功能主要包括两方面:
1、shell外壳 : 包裹在操作系统外层的软件层,方便用户和OS(操作系统)进行沟通
2、shell : 接受用户的输入,交给OS执行,得到结果反馈给用户
3、 shell的作用 :a.交互 b.保护OS
4、 shell是所以外壳程序的统称,笼统的概念 ,bash是一种具体的shell\ncentOS7的外壳程序是: bash
1、shell是做命令行解释的,给操作系统解释,同时将结果翻译给用户。
2、shell外壳会保护操作系统,并不是用户所有的命令都会传递到操作系统,对系统有危害性的命令会被阻止。
3、shell的运行原理:创建子进程,即子shell,子shell会从父shell中继承很多环境,如变量、命令全路径、文件描述符、当前工作目录、陷阱等等,其好处为子进程出现任何问题都不会影响父进程shell。
以我们熟悉的 Windows 来说,我们操作 Windows 并不是直接操作 Windows 内核,而是操作 Windows GUI (图形化界面) 提供的接口,比如我们双击运行一个 .exe 程序或者最大化/最小化一个窗口,Windows GUI 会将我们进行的这些操作翻译为 Windows 内核所能理解的指令,然后传递给 Windows 内核进行处理;当 Windows kernel 处理完毕后,GUI 又会将处理结果翻译为我们用户能够看懂的操作,这样我们与 Windows kernel 的交互成本就会被大大降低。
shell 对于 Linux 有同样的作用,主要是对我们的指令进行解析并传递给 Linux kernel,然后再将处理结果解析给用户;
同时,shell 还在变相的保护操作系统 – shell 会对用户传递的指令进行解析,如果它解析到非法指令,那么它就会直接抛出错误,并不会将错误指令传递给 kernel,这样使得 kernel 只用处理合法的指令,一定程度上保护了操作系统。
另外,为了防止用户的非法指令导致 shell 自身崩溃,shell 本身一般都不会去执行对应的指令,而是会派生子进程来执行用户得到指令,关于多进程的知识我们后面再仔细学习。
所以,shell 和 GUI 一样,本质上都是 kernel 外面的一层软件层 (外壳程序),用于连接用户与 kernel。
为了更好的理解 kernel 与 shell 的关系,下面我们举一个例子:
假设你是一个闷骚且害羞的程序员,你家很有钱有势,你爸是你们村的村长,你家有房有车,你自己的年薪也是几十万,妥妥的高富帅;你喜欢上了村里的一个姑娘如花(口味很重),但是你十分内向(主要是闷骚),不敢向如花表明你的心意。但是你们村中有一个十分厉害的媒婆,叫王婆,王婆在你们村方圆十里都是最厉害的媒婆,只要她出马基本上就没有拿不下的姑娘吧,所以你找上了王婆,让她去向如花说媒。王婆就去了如花家说媒。但是,如花说你是一个好人(好人卡+1),但是你们不适合。媒婆告知了你,但是你是一个十分专一的人,非如花不可,于是王婆又去替你再说说。你去了如花家发现如花正在和村里的另一个高富帅卿卿我我,并且已经见过父母,订婚了。但是你是一个十分固执的人,非如花不可,于是你还是三番五次的找王婆去给你再说一说;王婆试了几次之后发现这媒完全不可能,于是后面直接不搭理你了,也不再去找如花了。你看王婆直接不管你了,于是跟王婆说:“我爸是村长,王婆您再去给我说说吧。(不说要你好看)”王婆看这事不办不行,但是如果继续三番五次去说媒,说不成不说,自己的口碑也没了。最后,王婆想了一个好办法,王婆收了好几个实习的徒弟,然后每次你找王婆,王婆都找借口说自己没空,然后派实习生去找如花,这样即使失败了也可以说是因为徒弟业务不熟;这样即不得罪村长,也保住了自己的口碑。
在上面的例子中,王婆就相当于 shell,用来传递你 (用户) 的信息 (指令) 给如花 (kernel),然后将如花的信息反馈给你;同时,王婆拒绝多次去说媒,相当于 shell 拦截了非法指令,变相的保护了 kernel;最后,为了保证自己的口碑,王婆安排自己的徒弟去说媒,相当于 shell 为了防止自身崩溃,所以自己不会直接去执行指令,而是派生子进程去执行。
shell 是 “外壳程序” 的统称,不同 Linux 版本对应的 shell 程序可能不同,其中 bash 是标准的 GNU shell,所以它成为了所有 Linux 发行版上的标准 shell。 现在大多数现代 Linux 发行版都默认提供 Bash shell 。 对应上面的例子来说,shell 是媒婆,而 bash 是王婆。
Linux下有两种用户:超级用户 (root) 与 普通用户
超级用户:可以再linux系统下做任何事情,几乎不受权限的限制
普通用户:在linux下做权限范围内的事情
超级用户的命令提示符是“#”,普通用户的命令提示符是“$”
命令: su [用户名]
功能:切换用户
例如,要从root用户切换到普通用户user,则使用 su user。 要从普通用户user切换到root用户则使用 su root(root可以省略),此时系统会提示输入root用户的口令。
示例:
添加普通用户(root用户才有权限): adduser
从超级用户(root)切换到普通用户: su user
但是如果我们要从普通用户切换到超级用户(root),就需要输入 root 密码;普通用户切换到 root 用户有两种方式:
su:切换到 root 的当前目录
su -:直接切换到 root 的根目录;
删除普通用户(root用户才有权限):userdel -r user
注:Linux 出于安全考虑,从键盘输入的密码在终端上是不会回显的,也就是说我们输入密码时屏幕不会显示任何东西;
在工作中我们使用Linux的时候可能会出现这样一种状况:当前有一条指令必须拥有超级用户的权限才能执行,但我们不想切换用户,想直接让普通用户以root用户的身份去执行该指令;
sudo 指令可以满足我们的需求:
我们执行 sudo 指令发现了两个奇怪的现象:
1、使用 sudo 指令让我们拥有root用户的权限,按理来说应该提示我们输入root密码,但事实是它让输入我们自己用户的密码
2、我以 thj 的身份执行 sudo 指令,它提示 thj 用户不在 sudoers file 内,sudo 失败
上面这些现象是由 sudo 的机制造成的:sudo 存在的目的是为了 给受信任的用户提供最少的执行障碍,受信任的用户是指被添加到 sudoers 文件中的用户;也就是说,当我们存在于 sudoers 文件中时,说明 root 用户充分信任我们,所以当我们使用 sudo 指令提升权限时只需要输入自己的密码即可;而如果我们不在 sudoers 文件中,那么自然也不能通过 sudo 指令提权。可惜我们好像不被信任。
注:sudo 的有限时间为15分钟,即当我们使用 sudo 提权成功后,后面15分钟内再次使用 sudo 指令不需要再次输入密码。
在 Linux 下,文件的访问者被分为三类:
拥有者:文件和文件目录的所有者 – u (user)
所属组:文件和文件目录的所有者所在的组的用户 – g (group)
其他用户:除所有者和所属组用户之外的用户 – o (other)
关于文件的所有者和其他用户相信大家都很容易理解,但是为什么会有一个所属组呢?我们以一个例子说明:
假设一家公司要开发一款产品,该公司的老板奉行内部竞争理念,所以他把手下的人分为了两个组,让他们来研发同一款产品,最后哪个组的产品更优哪个组就拿额外的奖金;但是呢由于公司很穷,只买得起一台主机,这时候问题就出现了:两个组的成员公用一台主机,那么组内成员的代码如何进行共享呢?如果我把文件设置为私有,这样虽然另外一组的人看不到我的代码,但同时我的队友也看不到。而如果我把文件设置为共有,那么又可能有代码泄露的风险,为了解决这种情况,Linux 设计出了所属组的概念,我们可以把多个用户归为一个组,让组内的成员共享文件,组外的成员则受权限限制。
我们在 Linux 中查看一个文件/目录时,文件前面通常会出现很长一串字符:
他们对应的含义如下:
Linux系统不是以文件名后缀区分文件类型的,而是通过ll指令显示的文件属性中的第一个字符区分文件类型
第一个字符代表文件类型,后面九个字符三三一组分别代表文件拥有者、所属组和其他用户的权限,其中文件的权限一共分为三类:
r – 读权限:Read 对文件而言,具有读取文件内容的权限;对目录来说,具有浏览该目录信息的权限
w – 写权限:Write 对文件而言,具有修改文件内容的权限;对目录来说具有删除移动目录内文件的权限
x – 可执行权限:execute 对文件而言,具有执行文件的权限;对目录来说,具有进入目录的权限
– 表示没有该项权限
其中对应位置上有代表权限的字符说明该用户拥有对应权限,如果显示 - 则代表该用户没有对应权限:
文件类型
Liunx 中一共有七种文件:
d:目录
-:普通文件 (可执行程序也属于普通文件)
l:软链接(类似Windows的快捷方式)
b:块设备文件(例如硬盘、光驱等)
p:管道文件
c:字符设备文件(例如屏幕等串口设备)
s:套接口文件
文件后缀与文件类型
在之前我们就提到,Linux 中不以文件的后缀名来区分文件类型,文件后缀属于文件名的一部分,但这并不不代表我们不可以使用文件后缀来区分文件类型,即虽然在 Linux 眼中文件后缀没用,但是我们可以把文件后缀当作对用户的一个提示符号。但是Linux 中不区分文件后缀并不代表 Linux 下的各种工具不区分,比如 gcc、g++ ,这俩是有本质区别的。
字符表示法中的每一个字符所在位置所表示的结果只有两种可能,要么为真,要么为假,而真可用1表示,假可用0表示,因此我们可以将这三个字符换为三个二进制位,进而换为一个八进制位进行表示。如下:
格式:chmod [参数] 权限 文件名
功能:设置文件的访问权限
常用选项
注意:只有文件的拥有者和root才可以改变文件的权限
chmod 指令权限值的格式
法一:用户表示符 +/-/= 权限字符:
用户符号:
指令演示
减去拥有者的读写权限:chmod u-rw 文件名/目录名
减去所属组和其他用户的读权限:chmod g-r,o-r 文件名/目录名
加上拥有者,所属组,其他人的所有权限:chmod ugo+rwx test.txt/chmod a+rwx test.txt
我们知道root用户不受任何权限的约束,可以为所欲为,现在我们来演示一下root用户的强大:
这时test.txt的拥有者,所属组均为普通用户wei,而root用户是其他用户,按照权限设置,root用户应该没有任何权限,但实际它可以随意读写文件,不受任何约束,由此可见,这里的其他用户指的是除root用户以外的其他普通用户。
法二:三位八进制数字
文件的权限一共三种 – 读写执行,所以用三个二进制位就可以表示全部情况,如果用八进制则只需要一位:
指令演示
我们还可以使用chmod a= 权限 来进行各个用户整体的修改:
格式:chown [参数] 用户名 文件名
功能:修改文件的拥有者
常用选项
注意:当我们使用 chown 指令将属于我们的文件赋给别人时,需要获得别人的同意,所以在一般情况下我们是不能改变文件的拥有者的,只有 root 不受权限的约束。例如:root用户可以直接将属于 张三 的文件赋给 李四,而不需要征得 张三 和 李四 的同意。
指令演示
使用chown指令也可以连续修改拥有者和所属组:
格式:chgrp [参数] 用户组名 文件名
功能:修改文件或目录的所属组
常用选项
注意:和修改文件的拥有者一样,我们也不能直接修改文件的所属组,需要征得别人的同意,而 root 不受权限约束
指令演示
Linux下文件的默认权限如下 – 普通文件的默认权限是0666,目录文件的默认权限是0777,其中第一位数字代表这是三位八进制数,后面三位数字分别代表拥有者、所属组和其他人对文件的权限;但是我们发现,我们平时创建的文件的权限却不是上面的值。
这是因为创建文件或目录的时候除了受默认权限的约束之外,还要受到 umask (文件掩码) 的影响;假设默认权限是mask,则实际创建的出来的文件权限是: mask & ~umask。
权限掩码的作用是将在其中出现的权限 在起始权限中全部去掉,因为一个权限在 umask 中为1,那么其按位取反后再与默认权限按位与得到的结果一定为0;如果 umask 中为0,则其按位取反后与默认权限按位与后不影响默认权限的值。
格式:umask 权限值
功能:查看或修改文件掩码
修改用户权限掩码:umask 要修改的掩码
说明:将现有的存取权限减去权限掩码后,即可产生建立文件时预设权限;超级用户默认掩码值为0022,普通用户默认为0002。
查看文件掩码:
注意:凡是在权限掩码中出现的权限都不应该在最终权限出现。实际中我们只关注权限掩码的后三位。
指令演示
修改文件掩码:可以看到,当我们把文件掩码设置为000后,此时创建出的文件的最终权限就等于文件的默认权限。
格式:file [选项] 文件或目录
功能:辨识文件类型
常用选项
-c 详细显示指令执行过程,便于排错或分析程序执行的情形
-z 尝试去解读压缩文件的内容
指令演示
目录权限所代表的含义如下:
可执行权限:能否进入目录 – 如果目录没有可执行权限, 则无法cd到目录中
可读权限:能否查看目录中的文件内容 – 如果目录没有可读权限, 则无法用ls等命令查看目录中的文件内容
可写权限:能否在目录中创建与删除文件 – 如果目录没有可写权限, 则无法在目录中创建文件, 也无法在目录中删除文件
所以如果我们要进入一个目录,就必须有可执行权限,这也就是为什么普通文件的默认权限是666,而目录文件的默认权限是777的原因
注意事项
在一个Linux系统中通常有很多用户,那么有时就会有这样一种需求:不同的用户需要在一个公共的目录下进行临时文件的增删查改,这个公共目录通常由 root 用户创建,然后将目录权限修改为777;在Linux中,可以存在一些目录,拥有者和所属组是root,其它人允许以other的身份在该目录下进行文件的创建,读取,删除,修改等。如下的一个名为tmp的目录:该目录的拥有者和所属组均属于root,且other其它人的权限都是没有限制的,也就是说任何人都可以在里面读写文件。
但是这里出现了一个问题:由于这个公共目录的权限是777,所以任何一个用户都可以删除此目录下的文件,无论该文件是否属于自己。
可以看到,对于 wei 来说,test.txt 这个文件是不可写且不可执行的,wei 也确实不能对它进行这些操作,但是 wei 却能够直接删除test.txt,因为 test.txt 处于 tmp 这个目录之下,而这个目录对于 wei 是可读可写可执行的。
为了出来上面这种不科学的情况,Linux 引入了粘滞位的概念:
粘滞位是权限的一种特殊情况,它不影响不同用户在公共目录下的读写执行操作,但是它可以禁止不同用户之间互删文件,粘滞位设置的方式很简单,只需要在已有权限基础上加上 t 即可,并且添加时不用指定用户,Linux 会自动识别。
综上:当一个目录被设置为"粘滞位"(用chmod +t),则该目录下的文件只能由