第17章、程序管理与 SELinux 初探

17.1. 什么是程序 (Process)
由前面一连几个章节的数据看来,我们一直强调在 Linux 底下所有的指令与你能够进行的动作都与权限有关, 而系统如何判定你的权限呢?当然就是第十四章账号管理当中提到的 UID/GID 的相关概念,以及档案的属性相关性!再进一步来解释,你现在大概知道,在 Linux 系统当中:『触发任何一个事件时,系统都会将他定义成为一个程序,并且给予这个程序一个 ID ,称为 PID,同时依据启发这个程序的用户与相关属性关系,给予这个 PID 一组有效权限设定。 从此以后,这个 PID 能够在系统上面进行的动作,就与这个 PID 的权限有关了!

17.1.1. 程序与程序 (process & program): 子程序与父程序, fork-and-exec, 系统服务
我们如何产生一个程序呢?就是『执行一个程序或指令』就可以触发一个事件而取得一个 PID !系统应该是仅认识 binary file 的,那么当我们要让系统工作的时候,当然就是需要启动一个 binary file ,那个 binary file 就是程序 (program) !
每个程序都有三组人马的权限,每组人马都具有 r/w/x 的权限,所以:『不同的使用者身份执行这个 program 时,系统给予的权限也都不相同!』举例来说,我们可以利用 touch 来建立一个空的档案,当 root 执行这个 touch 指令时,他取得的是 UID/GID = 0/0 的权限,而当 dmtsai (UID/GID=501/501) 执行这个 touch 时,他的权限就跟 root 不同啦!我们将这个概念绘制成图示来瞧瞧如下:
这里写图片描述
程序触发后会加载到内存中成为一个个体,那就是程序。 为了操作系统可管理这个程序,因此程序有给予执行者的权限/属性等参数,并包括程序所需要的脚本与数据或档案数据等, 最后再给予一个 PID 。系统就是透过这个 PID 来判断该 process 是否具有权限进行工作的!他是很重要的!
我们要操作系统的时候,通常是利用联机程序或者直接在主机前面登入,然后取得我们的 shell (bash)在 /bin/bash ,那么同时间的每个人登入都是执行 /bin/bash !不过,每个人取得的权限就是不同!
这里写图片描述
也就是说,当我们登入并执行 bash 时,系统已经给我们一个 PID 了,这个 PID 就是依据登入者的 UID/GID (/etc/passwd) 来的。以上面的图 1.1.2 配合图 1.1.1 来做说明的话,我们知道 /bin/bash 是一个程序 (program),当 dmtsai 登入后,他取得一个 PID 号码为 2234 的程序,这个程序的 User/Group 都是 dmtsai ,而当这个程序进行其他作业时,例如上面提到的 touch 这个指令时, 那么由这个程序衍生出来的其他程序在一般状态下,也会沿用这个程序的相关权限的!
让我们将程序与程序作个总结:

  • 程序 (program):通常为 binary program ,放置在储存媒体中 (如硬盘、光盘、软盘、磁带等), 为实体档案的型态存在;
  • 程序 (process):程序被触发后,执行者的权限与属性、程序的程序代码与所需数据等都会被加载内存中, 操作系统并给予这个内存内的单元一个标识符 (PID),可以说,程序就是一个正在运作中的程序。

一、子程序与父程序:
在上面的说明里面,我们有提到所谓的『衍生出来的程序』,那是个啥咚咚?这样说好了,当我们登入系统后,会取得一个 bash 的 shell ,然后,我们用这个 bash 提供的接口去执行另一个指令,例如 /usr/bin/passwd 或者是 touch 等等,那些另外执行的指令也会被触发成为 PID !那个后来执行指令产生的 PID 就是『子程序』了,而在我们原本的 bash 环境下,就称为『父程序』了!
这里写图片描述
所以你必须要知道,程序彼此之间是有相关性的!以上面的图示来看,连续执行两个 bash 后,第二个 bash 的父程序就是前一个 bash。因为每个程序都有一个 PID ,那某个程序的父程序该如何判断?就透过 Parent PID (PPID) 来判断即可。此外,由十一章的 export 内容我们也探讨过环境变量的继承问题,子程序可以取得父程序的环境变量! 让我们来进行底下的练习,以了解什么是子程序/父程序。
这里写图片描述
很多朋友常常会发现:『咦!明明我将有问题的程序关闭了,怎么过一阵子他又自动的产生? 而且新产生的那个程序的 PID 与原先的还不一样,这是怎么回事呢?』不要怀疑,如果不是 crontab 工作排程的影响,肯定有一支父程序存在,所以你杀掉子程序后, 父程序就会主动再生一支!那怎么办?正所谓这:『擒贼先擒王』,找出那支父程序,然后将他删除!

二、fork and exec:过程调用的流程
其实子程序与父程序之间的关系还挺复杂的,最大的复杂点在于程序互相之间的呼叫。在 Linux 的过程调用通常称为 fork-and-exec 的流程 !程序都会藉由父程序以复制 (fork) 的方式产生一个一模一样的子程序, 然后被复制出来的子程序再以 exec 的方式来执行实际要进行的程序,最终就成为一个子程序的存在。 整个流程有点像底下这张图:
这里写图片描述
(1)系统先以 fork 的方式复制一个与父程序相同的暂存程序,这个程序与父程序唯一的差别就是 PID 不同! 但是这个暂存程序还会多一个 PPID 的参数,PPID 如前所述,就是父程序的程序标识符啦!然后(2)暂存程序开始以 exec 的方式加载实际要执行的程序,以上述图标来讲,新的程序名称为 qqq ,最终子程序的程序代码就会变成 qqq 了!

三、系统或网络服务:常驻在内存的程序
如果就我们之前学到的一些指令数据来看,其实我们下达的指令都很简单,包括用 ls 等等的,不过, 这些指令都是执行完就结束了。也就是说,该项指令被触发后所产生的 PID 很快就会终止! 那有没有一直在执行的程序啊?当然有啊!
常驻在内存当中的程序通常都是负责一些系统所提供的功能以服务用户各项任务,因此这些常驻程序就会被我们称为:服务 (daemon)。系统的服务非常的多, 不过主要大致分成系统本身所需要的服务,例如刚刚提到的 crond 及 atd ,还有 syslog 等等的。还有一些则是负责网络联机的服务,例如 Apache, named, postfix, vsftpd… 等等的。这些网络服务比较有趣的地方,在于这些程序被执行后,他会启动一个可以负责网络监听的端口口 (port) ,以提供外部客户端 (client) 的联机要求。

17.1.2. Linux 的多人多任务环境
我们现在知道了,其实在 Linux 底下执行一个指令时,系统会将相关的权限、属性、程序代码与数据等均加载内存, 并给予这个单元一个程序标识符 (PID),最终该指令可以进行的任务则与这个 PID 的权限有关。这样我们就可以简单的了解,为什么 Linux 这么多用户,但是即每个人都可以拥有自己的环境了! Linux 多人多任务环境的特色:

一、多人环境:
在 Linux 系统上面具有多种不同的账号, 每种账号都有其特殊的权限,只有一个人具有至高无上的权力,那就是 root (系统管理员)。除了 root 之外,其他人都必须要受一些限制的!而每个人进入 Linux 的环境设定都可以随着每个人的喜好来设定 ,因为每个人登入后取得的 shell 的 PID 不同!

二、多任务行为:
目前的 CPU 速度可高达几个 GHz。 所以 CPU 每秒就能够在各个程序之间进行切换!
CPU 切换程序的工作,与这些工作进入到 CPU 运作的排程 (CPU 排程,非 crontab 排程) 会影响到系统的整体效能! 目前 Linux 使用的多任务切换行为是非常棒的一个机制,几乎可以将 PC 的性能整个压榨出来! 由于效能非常好,因此当多人同时登入系统时,其实会感受到整部主机好像就为了你存在一般!

三、多重登入环境的七个基本终端窗口:
在 Linux 当中,默认提供了六个文字界面登入窗口,以及一个图形界面,你可以使用 [Alt]+[F1]…..[F7] 来切换不同的终端机界面,而且每个终端机界面的登入者还可以不同人! 其实,这也是多任务环境下所产生的一个情况!我们的 Linux 默认会启动六个终端机登入环境的程序,所以我们就会有六个终端机接口。 您也可以减少啊!就是减少启动的终端机程序就好了。详细的资料可以先查阅 /etc/inittab 这个档案,未来我们在开机管理流程 (第二十章) 会再仔细的介绍的!

四、特殊的程序管理行为:
Linux 几乎可以说绝对不会当机的!因为他可以在任何时候, 将某个被困住的程序杀掉,然后再重新执行该程序而不用重新启动!那么如果我在 Linux 下以文字界面登入,在屏幕当中显示错误讯息后就挂了~ 这个时候那默认的七个窗口就帮上忙啦!你可以随意的再按 [Alt]+[F1]…..[F7] 来切换到其他的终端机界面,然后以 ps -aux 找出刚刚的错误程序,然后给他 kill 一下,又回复正常!
因为每个程序之间可能是独立的,也可能有相依性, 只要到独立的程序当中,删除有问题的那个程序,当然他就可以被系统移除掉啦!

五、bash 环境下的工作管理 (job control)
我们登入 bash 之后, 就是取得一个名为 bash 的 PID 了,而在这个环境底下所执行的其他指令, 就几乎都是所谓的子程序了。那么,在这个单一的 bash 接口下,我还可以进行多个工作!举例来说,我可以这样做:
这里写图片描述
在这一串指令中,重点在那个 & 的功能,他表示将 file1 这个档案复制为 file2 ,且放置于背景中执行, 也就是说执行这一个命令之后,在这一个终端接口仍然可以做其他的工作!而当这一个指令 (cp file1 file2) 执行完毕之后,系统将会在你的终端接口显示完成的消息!

六、多人多任务的系统资源分配问题考虑:
多人多任务确实有很多的好处,但其实也有管理上的困扰, 通常你的机器便需要升级了,因为 CPU 的运算与 RAM 的大小可能就会不敷使用!

17.2. 工作管理 (job control)
这个工作管理 (job control) 是用在 bash 环境下的,也就是说:『当我们登入系统取得 bash shell 之后,在单一终端机接口下同时进行多个工作的行为管理 』。举例来说,我们在登入 bash 后, 想要一边复制档案、一边进行资料搜寻、一边进行编译,还可以一边进行 vi 程序撰写! 当然我们可以重复登入那六个文字接口的终端机环境中,不过,能不能在一个 bash 内达成? 当然可以啊!就是使用 job control 啦!

17.2.1. 什么是工作管理
应该要了解的是:『进行工作管理的行为中, 其实每个工作都是目前 bash 的子程序,亦即彼此之间是有相关性的。 我们无法以 job control 的方式由 tty1 的环境去管理 tty2 的 bash !』!
我们可以在 /etc/security/limits.conf (第十四章) 里面设定使用者同时可以登入的联机数,某些使用者可能仅能以一个联机来工作! 所以就得要了解一下这种工作管理的模式了!此外,这个章节内容也会牵涉到很多的数据流重导向!
由于假设我们只有一个终端接口,因此在可以出现提示字符让你操作的环境就称为前景 (foreground),至于其他工作就可以让你放入背景 (background) 去暂停或运作。要注意的是,放入背景的工作想要运作时, 他必须不能够与使用者互动。放入背景的工作是不可以使用 [ctrl]+c 来终止的』!
总之,要进行 bash 的 job control 必须要注意到的限制是:

  • 这些工作所触发的程序必须来自于你 shell 的子程序(只管理自己的 bash);
  • 前景:你可以控制与下达指令的这个环境称为前景的工作 (foreground);
  • 背景:可以自行运作的工作,你无法使用 [ctrl]+c 终止他,可使用 bg/fg 呼叫该工作;
  • 背景中『执行』的程序不能等待 terminal/shell 的输入(input) ;

17.2.2. job control 的管理:&, [ctrl]-z, jobs, fg, bg, kill
bash 只能够管理自己的工作而不能管理其他 bash 的工作,所以即使你是 root 也不能够将别人的 bash 底下的 job 给他拿过来执行。此外,又分前景与背景,然后在背景里面的工作状态又可以分为『暂停 (stop)』与『运作中 (running)』。那实际进行 job 控制的指令有哪些?

一、直接将指令丢到背景中『执行』的 &
我们在只有一个 bash 的环境下,如果想要同时进行多个工作, 那么可以将某些工作直接丢到背景环境当中,让我们可以继续操作前景的工作! 最简单的方法就是利用『 & 』这个玩意儿了!举个简单的例子,我们要将 /etc/ 整个备份成为 /tmp/etc.tar.gz 且不想要等待,那么可以这样做:
这里写图片描述
我在输入一个指令后,在该指令的最后面加上一个『 & 』代表将该指令丢到背景中, 此时 bash 会给予这个指令一个『工作号码(job number)』,就是那个 [1] !至于后面那个 8400 则是该指令所触发的『 PID 』了! 不过,如果你输入几个指令后,突然出现这个数据:
这里写图片描述
就代表 [1] 这个工作已经完成 (Done) ,该工作的指令则是接在后面那一串指令列。 另外,这个 & 代表:『将工作丢到背景中去执行』! 注意到那个『执行』的字眼!此外,这样的情况最大的好处是: 不怕被 [ctrl]+c 中断的! 此外,将工作丢到背景当中要特别注意资料的流向!包括上面的讯息就有出现错误讯息,导致我的前景被影响。 虽然只要按下 [enter] 就会出现提示字符。但如果我将刚刚那个指令改成:
这里写图片描述
在背景当中执行的指令,如果有 stdout 及 stderr 时,他的数据依旧是输出到屏幕上面的, 所以,我们会无法看到提示字符,当然也就无法完好的掌握前景工作。同时由于是背景工作的 tar , 此时你怎么按下 [ctrl]+c !所以最佳的状况就是利用数据流重导向, 将输出数据传送至某个档案中。我可以这样做:
这里写图片描述
输出的信息都给他传送到 /tmp/log.txt 当中,当然就不会影响到我们前景的作业了。

二、将『目前』的工作丢到背景中『暂停』:[ctrl]-z
如果我正在使用 vi ,却发现我有个档案不知道放在哪里,需要到 bash 环境下进行搜寻,此时是否要结束 vi 呢?当然不需要啊!只要暂时将 vi 给他丢到背景当中等待即可。 例如以下的案例:
这里写图片描述
这里写图片描述
在 vi 的一般模式下,按下 [ctrl] 及 z 这两个按键,屏幕上会出现 [1] ,表示这是第一个工作, 而那个 + 代表最近一个被丢进背景的工作,且目前在背景下预设会被取用的那个工作 (与 fg 这个指令有关 ) !而那个 Stopped 则代表目前这个工作的状态。在预设的情况下,使用 [ctrl]-z 丢到背景当中的工作都是『暂停』的状态!

三、观察目前的背景工作状态: jobs
这里写图片描述
如果想要知道目前有多少的工作在背景当中,就用 jobs 这个指令!直接下达 jobs 即可! 不过,如果想要知道该 job number 的 PID 号码,就加上 -l 这个参数! 在输出的信息当中,例如上表,仔细看到那个 + - 号!那个 + 代表预设的取用工作。 所以说:『目前我有两个工作在背景当中,两个工作都是暂停的, 而如果我仅输入 fg 时,那么那个 [2] 会被拿到前景当中来处理』!
其实 + 代表最近被放到背景的工作号码, - 代表最近最后第二个被放置到背景中的工作号码。 而超过最后第三个以后的工作,就不会有 +/- 符号存在了!

四、将背景工作拿到前景来处理:fg
有没有可以将背景工作拿到前景来处理的? 就是那个 fg (foreground) !举例来说,我们想要将上头范例当中的工作拿出来处理时:
这里写图片描述
这里写图片描述
经过 fg 指令就能够将背景工作拿到前景来处理了!不过比较有趣的是最后一个显示的结果,我们会发现 + 出现在第一个工作后! 这是因为你刚刚利用 fg %1 将第一号工作捉到前景后又放回背景,此时最后一个被放入背景的将变成 vi 那个指令动作, 所以当然 [1] 后面就会出现 + 了!另外,如果输入『 fg - 』 则代表将 - 号的那个工作号码拿出来,上面就是 [2]- 那个工作号码!

五、让工作在背景下的状态变成运作中: bg
如何让一个工作在背景底下『 Run 』呢?我们可以在底下这个案例当中来测试! 底下的测试要进行的快一点!
这里写图片描述
那个状态栏~以经由 Stopping 变成了 Running ! 指令列最后方多了一个 & 的符号! 代表该工作被启动在背景当中了!

六、管理背景当中的工作: kill
如果想要将该工作直接移除呢?或者是将该工作重新启动呢?这个时候就得需要给予该工作一个讯号 (signal) ,此时, kill 这个指令就派上用场了!
这里写图片描述
**这里写图片描述
-9 这个 signal 通常是用在『强制删除一个不正常的工作』时所使用的, -15 则是以正常步骤结束一项工作(15也是默认值),两者之间并不相同! 我用 vi 的时候,不是会产生一个 .filename.swp 的档案吗? 那么,当使用 -15 这个 signal 时, vi 会尝试以正常的步骤来结束掉该 vi 的工作, 所以 .filename.swp 会主动的被移除。但若是使用 -9 这个 signal 时,由于该 vi 工作会被强制移除掉,因此, .filename.swp 就会继续存在文件系统当中
其实, kill 的妙用是很无穷的!他搭配 signal 所详列的信息 (用 man 7 signal 去查阅相关资料) 可以让您有效的管理工作与程序 (Process),此外,那个 killall 也是同样的用法! 至于常用的 signal 您至少需要了解 1, 9, 15 这三个 signal 的意义才好。 此外, signal 除了以数值来表示之外,也可以使用讯号名称! 至于 signal number 与名称的对应, 使用 kill -l 就知道啦(L的小写) !
另外, kill 后面接的数字默认会是 PID ,如果想要管理 bash 的工作控制,就得要加上 %数字 了, 这点也得特别留意才行!

17.2.3. 脱机管理问题: nohup
我们在工作管理当中提到的『背景』指的是在终端机模式下可以避免 [crtl]-c 中断的一个情境, 并不是放到系统的背景去!所以,工作管理的背景依旧与终端机有关! 在这样的情况下,如果你是以远程联机方式连接到你的 Linux 主机,并且将工作以 & 的方式放到背景去, 请问,在工作尚未结束的情况下你脱机了,该工作不会继续进行,而是会被中断掉。
如果我的工作需要进行一大段时间,我又不能放置在背景底下,那该如何处理呢? 首先,你可以参考前一章的 at 来处理即可!因为 at 是将工作放置到系统背景, 而与终端机无关。如果不想要使用 at 的话,那你也可以尝试使用 nohup 这个指令来处理!这个 nohup 可以让你在脱机或注销系统后,还能够让工作继续进行。他的语法有点像这样:
这里写图片描述
上述指令需要注意的是, nohup 并不支持 bash 内建的指令,因此你的指令必须要是外部指令才行。
这里写图片描述
这里写图片描述
如果你再次登入的话,再使用 ps -l 去查阅你的程序,会发现 sleep500.sh 还在执行中!由于我们的程序最后会输出一个讯息,但是 nohup 与终端机其实无关了, 因此这个讯息的输出就会被导向『 ~/nohup.out 』,所以你才会看到上述指令中,当你输入 nohup 后, 会出现那个提示讯息。
如果你想要让在背景的工作在你注销后还能够继续的执行,那么使用 nohup 搭配 & 是不错的运作情境!

17.3. 程序管理
为什么程序管理这么重要呢?这是因为:

  • 首先,本章一开始就谈到的,我们在操作系统时的各项工作其实都是经过某个 PID 来达成的 (包括你的 bash 环境), 因此,能不能进行某项工作,就与该程序的权限有关了。
  • 再来,如果您的 Linux 系统是个很忙碌的系统,那么当整个系统资源快要被使用光时, 您是否能够找出最耗系统的那个程序,然后删除该程序,让系统恢复正常呢?
  • 此外,如果由于某个程序写的不好,导致产生一个有问题的程序在内存当中,您又该如何找出他,然后将他移除呢?
  • 如果同时有五六项工作在您的系统当中运作,但其中有一项工作才是最重要的, 该如何让那一项重要的工作被最优先执行呢?

所以一个称职的系统管理员,必须要熟悉程序的管理流程才行,否则当系统发生问题时,还真是很难解决问题! 底下我们会先介绍如何观察程序与程序的状态,然后再加以过程控制!

17.3.1. 程序的观察: ps (ps -l, ps aux, zombie), top, pstree
查阅系统上面正在运作当中的程序就是利用静态的 ps 或者是动态的 top,还能以 pstree 来查阅程序树之间的关系!

一、ps :将某个时间点的程序运作情况撷取下来
这里写图片描述
这里写图片描述
个人认为 ps 这个指令的 man page 不是很好查阅,因为很多不同的 Unix 都使用这个 ps 来查阅程序状态, 为了要符合不同版本的需求,所以这个 man page 写的非常的庞大!因此建议你,直接背两个比较不同的选项, 一个是只能查阅自己 bash 程序的『 ps -l 』一个则是可以查阅所有系统运作的程序『 ps aux 』 !注意,是『 ps aux 』没有那个减号 (-) !先来看看关于自己 bash 程序状态的观察:

  1. 仅观察自己的 bash 相关程序: ps -l
    这里写图片描述
    系统整体的程序运作是非常多的,但如果使用 ps -l 则仅列出与你的操作环境 (bash) 有关的程序而已, 亦即最上局的父程序会是你自己的 bash 而没有延伸到 init 这支程序去!那么 ps -l 秀出来的资料有哪些呢? 我们就来观察看看:

    • F:代表这个程序旗标 (process flags),说明这个程序的总结权限,常见号码有:
      o 若为 4 表示此程序的权限为 root ;
      o 若为 1 则表示此子程序仅进行复制(fork)而没有实际执行(exec)。

    • S:代表这个程序的状态 (STAT),主要的状态有:
      o R (Running):该程序正在运作中;
      o S (Sleep):开程序目前正在睡眠状态(idle),但可以被唤醒(signal)。
      o D :不可被唤醒的睡眠状态,通常这支程序可能在等待 I/O 的情况(ex>打印)
      o T :停止状态(stop),可能是在工作控制(背景暂停)或除错 (traced) 状态;
      o Z (Zombie):僵尸状态,程序已经终止但却无法被移除至内存外。

    • UID/PID/PPID:代表『此程序被该 UID 所拥有/程序的 PID 号码/此程序的父程序 PID 号码』

    • C:代表 CPU 使用率,单位为百分比;
    • PRI/NI:Priority/Nice 的缩写,代表此程序被 CPU 所执行的优先级,数值越小代表该程序越快被 CPU 执行。详细的 PRI 与 NI 将在下一小节说明。
    • ADDR/SZ/WCHAN:都与内存有关,ADDR 是 kernel function,指出该程序在内存的哪个部分,如果是个 running 的程序,一般就会显示『 - 』 / SZ 代表此程序用掉多少内存 / WCHAN 表示目前程序是否运作中,同样的, 若为 - 表示正在运作中。
    • TTY:登入者的终端机位置,若为远程登录则使用动态终端接口 (pts/n);
    • TIME:使用掉的 CPU 时间,注意,是此程序实际花费 CPU 运作的时间,而不是系统时间;
    • CMD:就是 command 的缩写,造成此程序的触发程序之指令为何。

所以你看到的 ps -l 输出讯息中,他说明的是:『bash 的程序属于 UID 为 0 的使用者,状态为睡眠 (sleep), 之所以为睡眠因为他触发了 ps (状态为 run) 之故。此程序的 PID 为 13639,优先执行顺序为 75 , 下达 bash 所取得的终端接口为 pts/1 ,运作状态为等待 (wait) 。』

  1. 观察系统所有程序: ps aux
    这里写图片描述
    你会发现 ps -l 与 ps aux 显示的项目并不相同!在 ps aux 显示的项目中,各字段的意义为:
    • USER:该 process 属于那个使用者账号的?
    • PID :该 process 的程序标识符。
    • %CPU:该 process 使用掉的 CPU 资源百分比;
    • %MEM:该 process 所占用的物理内存百分比;
    • VSZ :该 process 使用掉的虚拟内存量 (Kbytes)
    • RSS :该 process 占用的固定的内存量 (Kbytes)
    • TTY :该 process 是在那个终端机上面运作,若与终端机无关则显示 ?,另外, tty1-tty6 是本机上面的登入者程序,若为 pts/0 等等的,则表示为由网络连接进主机的程序。
    • STAT:该程序目前的状态,状态显示与 ps -l 的 S 旗标相同 (R/S/T/Z)
    • START:该 process 被触发启动的时间;
    • TIME :该 process 实际使用 CPU 运作的时间。
    • COMMAND:该程序的实际指令为何?

一般来说,ps aux 会依照 PID 的顺序来排序显示,我们还是以 13639 那个 PID 那行来说明!该行的意义为『 root 执行的 bash PID 为 13639,占用了 0.2% 的内存容量百分比,状态为休眠 (S),该程序启动的时间为 11:44 , 且取得的终端机环境为 pts/1 。』与 ps aux 看到的其实是同一个程序!这样可以理解吗? 让我们继续使用 ps 来观察一下其他的信息!
这里写图片描述
这里写图片描述
在进行一些测试时,都是以网络联机进主机来测试的,所以你会发现其实程序之间是有相关性的! 不过,其实还可以使用 pstree 来达成这个程序树!以上面的例子来看,是透过 sshd 提供的网络服务取得一个程序, 该程序提供 bash 给我使用,而我透过 bash 再去执行 ps axjf !
这里写图片描述
通常,造成僵尸程序的成因是因为该程序应该已经执行完毕,或者是因故应该要终止了, 但是该程序的父程序即无法完整的将该程序结束掉,而造成那个程序一直存在内存当中。 如果你发现在某个程序的 CMD 后面还接上 时,就代表该程序是僵尸程序,例如:
这里写图片描述
当系统不稳定的时候就容易造成所谓的僵尸程序,可能是因为程序写的不好,或者是使用者的操作习惯不良等等所造成。 如果你发现系统中很多僵尸程序时,要找出该程序的父程序,然后好好的做个追踪,好好的进行主机的环境优化! 看看有什么地方需要改善的,不要只是直接将他 kill 掉而已!不然的话,万一他一直产生,那可就麻烦了!
事实上,通常僵尸程序都已经无法控管,而直接是交给 init 这支程序来负责了,偏偏 init 是系统第一支执行的程序, 他是所有程序的父程序!我们无法杀掉该程序的 (杀掉他,系统就死掉了!),所以如果产生僵尸程序, 而系统过一阵子还没有办法透过核心非经常性的特殊处理来将该程序删除时,那你只好透过 reboot 的方式来将该程序抹去了!

二、top:动态观察程序的变化
相对于 ps 是撷取一个时间点的程序状态, top 则可以持续侦测程序运作的状态!使用方式如下:
这里写图片描述
这里写图片描述
其实 top 的功能非常多!可以用的按键也非常的多!可以参考 man top 的内部说明文件! 这里仅是列出一些自己常用的选项而已。接下来让我们实际观察一下如何使用 top 与 top 的画面吧!
这里写图片描述
top 也是个挺不错的程序观察工具!但不同于 ps 是静态的结果输出, top 这个程序可以持续的监测整个系统的程序工作状态。 在默认的情况下,每次更新程序资源的时间为 5 秒,不过,可以使用 -d 来进行修改。 top 主要分为两个画面,上面的画面为整个系统的资源使用状态,基本上总共有六行,显示的内容依序是:

  • 第一行(top…):这一行显示的信息分别为:
    o 目前的时间,亦即是 17:03:09 那个项目;
    o 开机到目前为止所经过的时间,亦即是 up 7days, 16:16 那个项目;
    o 已经登入系统的用户人数,亦即是 1 user项目;
    o 系统在 1, 5, 15 分钟的平均工作负载。我们在第十六章谈到的 batch 工作方式为负载小于 0.8 就是这个负载!代表的是 1, 5, 15 分钟,系统平均要负责运作几个程序(工作)的意思。 越小代表系统越闲置,若高于 1 得要注意你的系统程序是否太过繁复了!

  • 第二行(Tasks…):显示的是目前程序的总量与个别程序在什么状态(running, sleeping, stopped, zombie)。 比较需要注意的是最后的 zombie 那个数值,如果不是 0 !好好看看到底是那个 process 变成僵尸了?

  • 第三行(Cpus…):显示的是 CPU 的整体负载,每个项目可使用 ? 查阅。需要特别注意的是 %wa ,那个项目代表的是 I/O wait, 通常你的系统会变慢都是 I/O 产生的问题比较大!因此这里得要注意这个项目耗用 CPU 的资源! 另外,如果是多核心的设备,可以按下数字键『1』来切换成不同 CPU 的负载率。
  • 第四行与第五行:表示目前的物理内存与虚拟内存 (Mem/Swap) 的使用情况。 再次重申,要注意的是 swap 的使用量要尽量的少!如果 swap 被用的很大量,表示系统的物理内存实在不足!
  • 第六行:这个是当在 top 程序当中输入指令时,显示状态的地方。

至于 top 下半部分的画面,则是每个 process 使用的资源情况。比较需要注意的是:

  • PID :每个 process 的ID !
  • USER:该 process 所属的使用者;
  • PR :Priority 的简写,程序的优先执行顺序,越小越早被执行;
  • NI :Nice 的简写,与 Priority 有关,也是越小越早被执行;
  • %CPU:CPU 的使用率;
  • %MEM:内存的使用率;
  • TIME+:CPU 使用时间的累加;

top 预设使用 CPU 使用率 (%CPU) 作为排序的重点,如果你想要使用内存使用率排序,则可以按下『M』, 若要回复则按下『P』即可。如果想要离开 top 则按下『 q 』!如果你想要将 top 的结果输出成为档案时, 可以这样做:
这里写图片描述
可以帮助你将某个时段 top 观察到的结果存成档案,可以用在你想要在系统背景底下执行。 由于是背景底下执行,与终端机的屏幕大小无关,因此可以得到全部的程序画面!那如果你想要观察的程序 CPU 与内存使用率都很低,结果老是无法在第一行显示时,我们可以仅观察单一程序!如下所示:
这里写图片描述
就只会有一支程序给你看!那么如果我想要在 top 底下进行一些动作呢? 比方说,修改 NI 这个数值呢?可以这样做:
这里写图片描述
这里写图片描述
在你完成上面的动作后,在状态栏会出现如下的信息:
这里写图片描述
接下来你就会看到如下的显示画面!
这里写图片描述
底线的地方就是修改了之后所产生的效果!一般来说,如果想要找出最损耗 CPU 资源的那个程序时,大多使用的就是 top 这支程序!然后强制以 CPU 使用资源来排序 (在 top 当中按下 P 即可)!

三、pstree
这里写图片描述
这里写图片描述
如果要找程序之间的相关性,这个 pstree 真是好用到不行!直接输入 pstree 可以查到程序相关性,如上表所示,还会使用线段将相关性程序链接起来! 一般链接符号可以使用 ASCII 码即可,但有时因为语系问题会主动的以 Unicode 的符号来链接, 但因为可能终端机无法支持该编码,或许会造成乱码问题。因此可以加上 -A 选项来克服此类线段乱码问题。
由 pstree 的输出我们也可以很清楚的知道,所有的程序都是依附在 init 这支程序底下的! 仔细看一下,这支程序的 PID 是一号!因为他是由 Linux 核心所主动呼叫的第一支程序!所以 PID 就是一号了。 这也是我们刚刚提到僵尸程序时有提到,为啥发生僵尸程序需要重新启动? 因为 init 要重新启动,而重新启动 init 就是 reboot !
如果还想要知道 PID 与所属使用者,加上 -u 及 -p 两个参数即可。 如果子程序挂点或者是老是砍不掉子程序时,该如何找到父程序吗?用这个 pstree 就对了!

17.3.2. 程序的管理: signal, kill, killall
程序之间是可以互相控制的!举例来说,你可以关闭、重新启动服务器软件,服务器软件本身是个程序, 你既然可以让她关闭或启动,当然就是可以控制该程序!那么程序是如何互相管理的呢?其实是透过给予该程序一个讯号 (signal) 去告知该程序你想要让她作什么!
我们也在本章之前的 bash 工作管理当中提到过, 要给予某个已经存在背景中的工作某些动作时,是直接给予一个讯号给该工作号码即可。那么到底有多少 signal 呢? 你可以使用 kill -l (小写的 L ) 或者是 man 7 signal 都可以查询到!主要的讯号代号与名称对应及内容是:
这里写图片描述
这里写图片描述
上面仅是常见的 signal 而已,更多的讯号信息请自行 man 7 signal !一般来说,你只要记得『1, 9, 15』这三个号码的意义即可。那么我们如何传送一个讯号给某个程序呢?就透过 kill 或 killall !底下分别来看看:

一、kill -signal PID
kill 可以帮我们将这个 signal 传送给某个工作 (%jobnumber) 或者是某个 PID (直接输入数字)。 要再次强调的是: kill 后面直接加数字与加上 %number 的情况是不同的 ! 因为工作控制中有 1 号工作,但是 PID 1 号则是与指『 init 』这支程序!你怎么可以将 init 关闭呢? 关闭 init ,你的系统就当掉了!所以记得那个 % 是我们用在工作控制的!
这里写图片描述
如果未来你想要将某个莫名其妙的登入者的联机删除的话,就可以透过使用 pstree -p 找到相关程序, 然后再以 kill -9 将该程序删除,该条联机就会被踢掉了!

二、killall -signal 指令名称
由于 kill 后面必须要加上 PID (或者是 job number),所以,通常 kill 都会配合 ps, pstree 等指令,因为我们必须要找到相对应的那个程序的 ID !有没有可以利用『下达指令的名称』来给予讯号的?举例来说,能不能直接将 syslog 这个程序给予一个 SIGHUP 的讯号呢?可以的!用 killall !
这里写图片描述
这里写图片描述
总之,要删除某个程序,我们可以使用 PID 或者是启动该程序的指令名称, 而如果要删除某个服务最简单的方法就是利用 killall , 因为他可以将系统当中所有以某个指令名称启动的程序全部删除。 举例来说,上面的范例二当中,系统内所有以 httpd 启动的程序,就会通通的被删除!

17.3.3. 关于程序的执行顺序: priority, nice, renice
我们知道 Linux 是多人多任务的环境,由 top 的输出结果我们也发现, 系统同时间有非常多的程序在运行中,只是绝大部分的程序都在休眠 (sleeping) 状态而已。如果所有的程序同时被唤醒,那么 CPU 应该要先处理那个程序呢?也就是说,那个程序被执行的优先序比较高? 这就得要考虑到程序的优先执行序 (Priority)CPU 排程

一、Priority 与 Nice 值
我们知道 CPU 一秒钟可以运作多达数 G 的微指令次数,透过核心的 CPU 排程可以让各程序被 CPU 所切换运作, 因此每个程序在一秒钟内或多或少都会被 CPU 执行部分的脚本。如果程序都是集中在一个队列中等待 CPU 的运作, 而不具有优先级之分,也就是像我们去游乐场玩热门游戏需要排队一样,每个人都是照顺序来! 你玩过一遍后还想再玩 (没有执行完毕),请到后面继续排队等待。情况有点像底下这样:
这里写图片描述
上图中假设 pro1, pro2 是紧急的程序, pro3, pro4 是一般的程序,在这样的环境中,由于不具有优先级,pro1, pro2 还是得要继续等待而没有优待!如果 pro3, pro4 的工作又臭又长!那么紧急的 pro1, pro2 就得要等待个老半天才能够完成!所以我们要将程序分优先级!如果优先级较高则运作次数可以较多次, 而不需要与较慢优先的程序抢位置!我们可以将程序的优先级与 CPU 排程进行如下图的解释:
这里写图片描述
如上图所示,具高优先权的 pro1, pro2 可以被取用两次,而较不重要的 pro3, pro4 则运作次数较少。 如此一来 pro1, pro2 就可以较快被完成!要注意,上图仅是示意图,并非较优先者一定会被运作两次! 为了要达到上述的功能,我们 Linux 给予程序一个所谓的『优先执行序 (priority, PRI)』, 这个 PRI 值越低代表越优先的意思。不过这个 PRI 值是由核心动态调整的, 用户无法直接调整 PRI 值的。先来瞧瞧 PRI 曾在哪里出现?
这里写图片描述
由于 PRI 是核心动态调整的,我们用户也无权去干涉 PRI !那如果你想要调整程序的优先执行序时,就得要透过 Nice 值了!Nice 值就是上表的 NI !一般来说, PRI 与 NI 的相关性如下:
PRI(new) = PRI(old) + nice
不过你要特别留意到,如果原本的 PRI 是 50 ,并不是我们给予一个 nice = 5 ,就会让 PRI 变成 55 ! 因为 PRI 是系统『动态』决定的,所以虽然 nice 值是可以影响 PRI ,不过, 最终的 PRI 仍是要经过系统分析后才会决定的。另外, nice 值是有正负的,而既然 PRI 越小越早被执行, 所以,当 nice 值为负值时,那么该程序就会降低 PRI 值,亦即会变的较优先被处理。此外,你必须要留意到:

  • nice 值可调整的范围为 -20 ~ 19 ;
  • root 可随意调整自己或他人程序的 Nice 值,且范围为 -20 ~ 19 ;
  • 一般用户仅可调整自己程序的 Nice 值,且范围仅为 0 ~ 19 (避免一般用户抢占系统资源);
  • 一般使用者仅可将 nice 值越调越高,例如本来 nice 为 5 ,则未来仅能调整到大于 5;

这也就是说,要调整某个程序的优先执行序,就是『调整该程序的 nice 值』!那么如何给予某个程序 nice 值呢?有两种方式,分别是:

  • 一开始执行程序就立即给予一个特定的 nice 值:用 nice 指令;
  • 调整某个已经存在的 PID 的 nice 值:用 renice 指令。

二、nice :新执行的指令即给予新的 nice 值
这里写图片描述
这里写图片描述
就如同前面说的, nice 是用来调整程序的执行优先级!这里只是一个执行的范例罢了! 通常什么时候要将 nice 值调大呢?举例来说,系统的背景工作中, 某些比较不重要的程序之进行:例如备份工作!由于备份工作相当的耗系统资源, 这个时候就可以将备份的指令之 nice 值调大一些,可以使系统的资源分配的更为公平!

三、renice :已存在程序的 nice 重新调整
这里写图片描述
如果要调整的是已经存在的某个程序的话,那么就得要使用 renice 了。使用的方法很简单, renice 后面接上数值及 PID 即可。因为后面接的是 PID ,所以你务必要以 ps 或者其他程序观察的指令去找出 PID 才行!
由上面这个范例当中我们也看的出来,虽然修改的是 bash 那个程序,但是该程序所触发的 ps 指令当中的 nice 也会继承而为 10 !整个 nice 值是可以在父程序 –> 子程序之间传递的! 另外,除了 renice 之外,其实那个 top 同样的也是可以调整 nice 值的!

17.3.4. 系统资源的观察: free, uname, uptime, netstat, dmesg, vmstat
除了系统的程序之外,我们还必须就系统的一些资源进行检查!举例来说,我们使用 top 可以看到很多系统的资源!那么,还有没有其他的工具可以查阅的? 当然有啊!

一、free :观察内存使用情况
这里写图片描述
我的系统当中有 725MB 左右的物理内存,我的 swap 有 1GB 左右, 那我使用 free -m 以 MBytes 来显示时,就会出现上面的信息。Mem 那一行显示的是物理内存的量, Swap 则是虚拟内存的量。 total 是总量, used 是已被使用的量, free 则是剩余可用的量。 后面的 shared/buffers/cached 则是在已被使用的量当中,用来作为缓冲及快取的量。
仔细的看到范例一的输出,我们的 Linux 测试用主机是很平凡的,根本没有什么工作, 但是,我的物理内存是几乎被用光光的情况!不过,至少有 132MB 用在缓冲记忆 (buffers) 工作, 287MB 则用在快取 (cached) 工作,也就是说,系统是『很有效率的将所有的内存用光光』, 目的是为了让系统的存取效能加速!
物理内存(Mem)被用光是正常的!而需要注意的反而是 swap 的量。一般来说, swap 最好不要被使用,尤其 swap 最好不要被使用超过 20% 以上, 如果您发现 swap 的用量超过 20% ,那么,最好还是买物理内存来插吧! 因为, Swap 的效能跟物理内存实在差很多,而系统会使用到 swap , 绝对是因为物理内存不足了才会这样做的!

二、uname:查阅系统与核心相关信息
这里写图片描述
这里写图片描述
uname 可以列出目前系统的核心版本、 主要硬件平台以及 CPU 类型等等的信息。以上面范例一的状态来说,我的 Linux 主机使用的核心名称为 Linux,而主机名为 www.vbird.tsai,核心的版本为 2.6.18-92.el5 ,该核心版本建立的日期为 2008/6/10,适用的硬件平台为 i386 以上等级的硬件平台。

三、uptime:观察系统启动时间与工作负载
这个指令很单纯!就是显示出目前系统已经开机多久的时间,以及 1, 5, 15 分钟的平均负载就是了。还记得 top 吧?这个 uptime 可以显示出 top 画面的最上面一行!
这里写图片描述

四、netstat :追踪网络或插槽文件
这个指令比较常被用在网络的监控方面,不过,在程序管理方面也是需要了解的! 这个指令的执行如下所示:基本上, netstat 的输出分为两大部分,分别是网络与系统自己的程序相关性部分:
这里写图片描述
在上面的结果当中,显示了两个部分,分别是网络的联机以及 linux 上面的 socket 程序相关性部分。 我们先来看看因特网联机情况的部分:

  • Proto:网络的封包协议,主要分为 TCP 与 UDP 封包,相关资料请参考服务器篇;
  • Recv-Q:非由用户程序链接到此 socket 的复制的总 bytes 数;
  • Send-Q:非由远程主机传送过来的 acknowledged 总 bytes 数;
  • Local Address :本地端的 IP:port 情况;
  • Foreign Address:远程主机的 IP:port 情况;
  • State :联机状态,主要有建立(ESTABLISED)及监听(LISTEN);

我们看上面仅有一条联机的数据,他的意义是:『透过 TCP 封包的联机,远程的 192.168.:vrtl.. 联机到本地端的 192.168.201.110:ssh ,这条联机状态是建立 (ESTABLISHED) 的状态!』至于更多的网络环境说明, 就得到另一本服务器篇查阅!
除了网络上的联机之外,其实 Linux 系统上面的程序是可以接收不同程序所发送来的信息,那就是 Linux 上头的插槽档 (socket file)。我们在第六章的档案种类有稍微提到 socket 档案, 但当时未谈到程序的概念,所以没有深入谈论。socket file 可以沟通两个程序之间的信息,因此程序可以取得对方传送过来的资料。 由于有 socket file,因此类似 X Window 这种需要透过网络连接的软件,目前新版的 distributions 就以 socket 来进行窗口接口的联机沟通了。上表中 socket file 的输出字段有:

  • Proto :一般就是 unix ;
  • RefCnt:连接到此 socket 的程序数量;
  • Flags :联机的旗标;
  • Type :socket 存取的类型。主要有确认联机的 STREAM 与不需确认的 DGRAM 两种;
  • State :若为 CONNECTED 表示多个程序之间已经联机建立。
  • Path :连接到此 socket 的相关程序的路径!或者是相关数据输出的路径。

以上表的输出为例,最后那三行在 /tmp/.xx 底下的数据,就是 X Window 窗口接口的相关程序! 而 PATH 指向的就是这些程序要交换数据的插槽档案!那么 netstat 可以帮我们进行什么任务呢? 我们先来看看,利用 netstat 去看看我们的哪些程序有启动哪些网络的『后门』呢?
这里写图片描述
很多朋友常常有疑问,那就是,我的主机目前到底开了几个门(ports) !其实,不论主机提供什么样的服务, 一定必须要有相对应的 program 在主机上面执行才行!举例来说,我们的 Linux 主机提供的就是 WWW 服务,那么我的主机当然有一个程序在提供 WWW 的服务!那就是 Apache 这个软件所提供的! 所以,当我执行了这个程序之后,我的系统自然就可以提供 WWW 的服务了。那如何关闭啊? 就关掉该程序所触发的那个程序就好了!例如上面的范例三所提供的例子!

五、dmesg :分析核心产生的讯息
系统在开机的时候,核心会去侦测系统的硬件,你的某些硬件到底有没有被捉到,那就与这个时候的侦测有关。 但是这些侦测的过程要不是没有显示在屏幕上,就是很飞快的在屏幕上一闪而逝!使用 dmesg 把核心侦测的讯息捉出来!
所有核心侦测的讯息,不管是开机时候还是系统运作过程中,反正只要是核心产生的讯息,都会被记录到内存中的某个保护区段。 dmesg 这个指令就能够将该区段的讯息读出来的!因为讯息实在太多了,所以执行时可以加入这个管线指令『 | more 』来使画面暂停!
这里写图片描述
由范例二就知道我这部主机的硬盘的格式了!还可以查阅能不能找到网络卡!网络卡的代号是 eth ,所以,直接输入 dmesg | grep -i eth 试看看!

六、vmstat :侦测系统资源变化
如果你想要动态的了解一下系统资源的运作,那么用这个 vmstat !vmstat 可以侦测『 CPU / 内存 / 磁盘输入输出状态 』等等,如果你想要了解一部繁忙的系统到底是哪个环节最累人, 可以使用 vmstat 分析看看。底下是常见的选项与参数说明:
这里写图片描述
这里写图片描述
利用 vmstat 甚至可以进行追踪!你可以使用类似『 vmstat 5 』代表每五秒钟更新一次,且无穷的更新!直到你按下 [ctrl]-c 为止。如果你想要实时的知道系统资源的运作状态,这个指令就不能不知道!那么上面的表格各项字段的意义为何? 基本说明如下:

  • 内存字段 (procs) 的项目分别为:
    r :等待运作中的程序数量;b:不可被唤醒的程序数量。这两个项目越多,代表系统越忙碌 (因为系统太忙,所以很多程序就无法被执行或一直在等待而无法被唤醒之故)。
  • 内存字段 (memory) 项目分别为:
    swpd:虚拟内存被使用的容量; free:未被使用的内存容量; buff:用于缓冲存储器; cache:用于高速缓存。 这部份则与 free 是相同的。
  • 内存置换空间 (swap) 的项目分别为:
    si:由磁盘中将程序取出的量; so:由于内存不足而将没用到的程序写入到磁盘的 swap 的容量。 如果 si/so 的数值太大,表示内存内的数据常常得在磁盘与主存储器之间传来传去,系统效能会很差!
  • 磁盘读写 (io) 的项目分别为:
    bi:由磁盘写入的区块数量; bo:写入到磁盘去的区块数量。如果这部份的值越高,代表系统的 I/O 非常忙碌!
  • 系统 (system) 的项目分别为:
    in:每秒被中断的程序次数; cs:每秒钟进行的事件切换次数;这两个数值越大,代表系统与接口设备的沟通非常频繁! 这些接口设备当然包括磁盘、网络卡、时间钟等。
  • CPU 的项目分别为:
    us:非核心层的 CPU 使用状态; sy:核心层所使用的 CPU 状态; id:闲置的状态; wa:等待 I/O 所耗费的 CPU 状态; st:被虚拟机 (virtual machine) 所盗用的 CPU 使用状态 (2.6.11 以后才支持)。

由于鸟哥的机器是测试机,所以并没有什么 I/O 或者是 CPU 忙碌的情况。如果改天你的服务器非常忙碌时, 记得使用 vmstat 去看看,到底是哪个部分的资源被使用的最为频繁!一般来说,如果 I/O 部分很忙碌的话,你的系统会变的非常慢! 让我们再来看看,那么磁盘的部分该如何观察:
这里写图片描述
详细的各字段就请诸位大德查阅一下 man vmstat !反正与读写有关!

17.4. 特殊档案与程序
我们在第七章曾经谈到特殊权限的 SUID/SGID/SBIT ,虽然第七章已经将这三种特殊权限作了详细的解释,不过,我们依旧要来探讨的是,那么到底这些权限对于你的『程序』是如何影响的? 此外,程序可能会使用到系统资源,举例来说,磁盘就是其中一项资源。哪天你在 umount 磁盘时,系统老是出现『 device is busy 』的字样~到底是怎么回事啊?我们底下就来谈一谈这些和程序有关系的细节部分:

17.4.1. 具有 SUID/SGID 权限的指令执行状态
SUID 的权限其实与程序的相关性非常的大!为什么呢?先来看看 SUID 的程序是如何被一般用户执行,且具有什么特色呢?

  • SUID 权限仅对二进制程序(binary program)有效;
  • 执行者对于该程序需要具有 x 的可执行权限;
  • 本权限仅在执行该程序的过程中有效 (run-time);
  • 执行者将具有该程序拥有者 (owner) 的权限。

所以说,整个 SUID 的权限会生效是由于『具有该权限的程序被触发』,而我们知道一个程序被触发会变成程序, 所以执行者可以具有程序拥有者的权限就是在该程序变成程序的那个时候!第七章我们还没谈到程序的概念, 所以你或许那时候会视得很奇怪,为啥执行了 passwd 后你就具有 root 的权限呢?不都是一般使用者执行的吗? 这是因为你在触发 passwd 后,会取得一个新的程序与 PID,该 PID 产生时透过 SUID 来给予该 PID 特殊的权限设定重点内容! 我们使用 dmtsai 登入系统且执行 passwd 后,透过工作控制来理解一下!
这里写图片描述
从上表的结果我们可以发现,底线的部分是属于 dmtsai 这个一般账号的权限,特殊字体的则是 root 的权限! 但你看到了, passwd 确实是由 bash 衍生出来的 !不过就是权限不一样!透过这样的解析, 你也会比较清楚为何不同程序所产生的权限不同了!这是由于『SUID 程序运作过程中产生的程序』的关系!
那么既然 SUID/SGID 的权限是比较可怕的,您该如何查询整个系统的 SUID/SGID 的档案呢?使用 find 即可!
find / -perm +6000

17.4.2. /proc/* 代表的意义
其实,我们之前提到的所谓的程序都是在内存当中!而内存当中的数据又都是写入到 /proc/* 这个目录下的,所以我们当然可以直接观察 /proc 这个目录当中的档案! 如果你观察过 /proc 这个目录的话,应该会发现他有点像这样:
这里写图片描述
这里写图片描述
基本上,目前主机上面的各个程序的 PID 都是以目录的型态存在于 /proc 当中。 举例来说,我们开机所执行的第一支程序 init 他的 PID 是 1 , 这个 PID 的所有相关信息都写入在 /proc/1/* 当中!若我们直接观察 PID 为 1 的数据好了,他有点像这样:
这里写图片描述
里面的数据还挺多的,比较有趣的其实是两个档案,分别是:

  • cmdline:这个程序被启动的指令串;
  • environ:这个程序的环境变量内容。

如果你查阅一下 cmdline 的话,就会发现:
这里写图片描述
就是这个指令、选项与参数启动 init 的!这还是跟某个特定的 PID 有关的内容,如果是针对整个 Linux 系统相关的参数呢?那就是在 /proc 目录底下的档案!相关的档案与对应的内容是这样的: (注3)
这里写图片描述
这里写图片描述
其实,上面这些档案在此建议您可以使用 cat 去查阅看看,不必深入了解, 不过,观看过档案内容后,毕竟会比较有感觉!如果未来您想要自行撰写某些工具软件, 那么这个目录底下的相关档案可能会对您有点帮助的!

17.4.3. 查询已开启档案或已执行程序开启之档案: fuser, lsof, pidof
其实还有一些与程序相关的指令可以值得参考与应用的,我们来谈一谈:

一、fuser:藉由档案(或文件系统)找出正在使用该档案的程序
有的时候我想要知道我的程序到底在这次启动过程中开启了多少档案,可以利用 fuser 来观察! 举例来说,你如果卸除时发现系统通知:『 device is busy 』,那表示这个文件系统正在忙碌中, 表示有某支程序有利用到该文件系统!那么你就可以利用 fuser 来追踪!fuser 语法有点像这样:
这里写图片描述
他说『.』底下有个 PID 为 20639 的程序,该程序属于 root 且指令为 bash 。 比较有趣的是那个 ACCESS 的项目,那个项目代表的意义为:

  • c :此程序在当前的目录下(非次目录);
  • e :可被触发为执行状态;
  • f :是一个被开启的档案;
  • r :代表顶层目录 (root directory);
  • F :该档案被开启了,不过在等待回应中;
  • m :可能为分享的动态函式库;

那如果你想要查阅某个文件系统底下有多少程序正在占用该文件系统时,那个 -m 的选项就很有帮助了! 我的测试主机仅有分割出 /, /boot, /home ,所以无法进行测试。不过好在还有个 /proc 的虚拟文件系统, 让我们来了解一下这个 /proc 的文件系统有多少程序正在利用他!
这里写图片描述
也可以仅针对单一档案!看一下底下的案例先:
这里写图片描述
透过这个 fuser 我们可以找出使用该档案、目录的程序,藉以观察! 他的重点与 ps, pstree 不同。 fuser 可以让我们了解到某个档案 (或文件系统) 目前正在被哪些程序所利用!

二、lsof :列出被程序所开启的档案文件名
使用 lsof查出某个程序开启或者使用的档案与装置。
这里写图片描述
这里写图片描述
这里写图片描述
这个指令可以找出您想要知道的某个程序是否有启用哪些信息?例如上头提到的范例四的执行结果!

三、pidof :找出某支正在执行的程序的 PID
这里写图片描述
这里写图片描述
透过这个 pidof 指令,并且配合 ps aux 与正规表示法,就可以很轻易的找到您所想要的程序内容了。

17.5. SELinux 初探
17.5.1. 什么是 SELinux: 目标, DAC, MAC
什么是 SELinux 呢?其实他是『 Security Enhanced Linux 』的缩写,字面上的意义就是安全强化的 Linux 之意 !那么所谓的『安全强化』是强化哪个部分? 是网络资安还是权限管理?底下就让我们来谈谈吧!

一、当初设计的目标:避免资源的误用
举例来说,如果有个不是很懂系统的系统管理员为了自己设定的方便,将网页所在目录 /var/www/html/ 的权限设定为 drwxrwxrwx 时,你觉得会有什么事情发生?
现在我们知道所有的系统资源都是透过程序来进行存取的,那么 /var/www/html/ 如果设定为 777 , 代表所有程序均可对该目录存取,万一你真的有启动 WWW 服务器软件,那么该软件所触发的程序将可以写入该目录, 而该程序即是对整个 Internet 提供服务的!只要有心人接触到这支程序,而且该程序刚好又有提供用户进行写入的功能, 那么外部的人很可能就会对你的系统写入些莫名其妙的东西!那可真是不得了!一个小小的 777 问题可是大大的!
为了控管这方面的权限与程序的问题,所以美国国家安全局就着手处理操作系统这方面的控管。 由于 Linux 是自由软件,程序代码都是公开的,因此她们便使用 Linux 来作为研究的目标, 最后更将研究的结果整合到 Linux 核心里面去,那就是 SELinux !更多的 SELinux 相关说明可以参考: http://www.nsa.gov/research/selinux/
这也就是说:其实 SELinux 是在进行程序、档案等细部权限设定依据的一个核心模块! 由于启动网络服务的也是程序,因此刚好也能够控制网络服务能否存取系统资源的一道关卡! 所以,在讲到 SELinux 对系统的访问控制之前,我们得先来回顾一下之前谈到的系统档案权限与用户之间的关系。 因为先谈完这个你才会知道为何需要 SELinux 的!

二、传统的档案权限与账号关系:自主式访问控制, DAC
我们第十四章的内容,知道系统的账号主要分为系统管理员 (root) 与一般用户,而这两种身份能否使用系统上面的档案资源则与 rwx 的权限设定有关。 不过你要注意的是,各种权限设定对 root 是无效的。因此,当某个程序想要对档案进行存取时, 系统就会根据该程序的拥有者/群组,并比对档案的权限,若通过权限检查,就可以存取该档案了。
这种存取文件系统的方式被称为『自主式访问控制 (Discretionary Access Control, DAC)』,基本上,就是依据程序的拥有者与档案资源的 rwx 权限来决定有无存取的能力。 不过这种 DAC 的访问控制有几个困扰,那就是:

  • root 具有最高的权限:如果不小心某支程序被有心人士取得, 且该程序属于 root 的权限,那么这支程序就可以在系统上进行任何资源的存取!真是要命!
  • 用户可以取得程序来变更档案资源的访问权限:如果你不小心将某个目录的权限设定为 777 ,由于对任何人的权限会变成 rwx ,因此该目录就会被任何人所任意存取!

这些问题是非常严重的!尤其是当你的系统是被某些漫不经心的系统管理员所掌控时!

三、以政策规则设定特定程序读取特定档案:委任式访问控制, MAC
现在我们知道 DAC 的困扰就是当用户取得程序后,他可以藉由这支程序与自己默认的权限来处理他自己的档案资源。 万一这个用户对 Linux 系统不熟,那就很可能会有资源误用的问题产生。为了避免 DAC 容易发生的问题,因此 SELinux 导入了委任式访问控制 (Mandatory Access Control, MAC) 的方法!
委任式访问控制 (MAC) 可以针对特定的程序与特定的档案资源来进行权限的控管! 也就是说,即使你是 root ,那么在使用不同的程序时,你所能取得的权限并不一定是 root , 而得要看当时该程序的设定而定。如此一来,我们针对控制的『主体』变成了『程序』而不是用户了! 此外,这个主体程序也不能任意使用系统档案资源,因为每个档案资源也有针对该主体程序设定可取用的权限! 如此一来,控件目的就细的多了!但整个系统程序那么多、档案那么多,一项一项控制可就没完没了! 所以 SELinux 也提供一些预设的政策 (Policy) ,并在该政策内提供多个规则 (rule) ,让你可以选择是否启用该控制规则!
在委任式访问控制的设定下,我们的程序能够活动的空间就变小了!举例来说, WWW 服务器软件的达成程序为 httpd 这支程序, 而默认情况下, httpd 仅能在 /var/www/ 这个目录底下存取档案,如果 httpd 这个程序想要到其他目录去存取数据时, 除了规则设定要开放外,目标目录也得要设定成 httpd 可读取的模式 (type) 才行!限制非常多! 所以,即使不小心 httpd 被 cracker 取得了控制权,他也无权浏览 /etc/shadow 等重要的配置文件!

17.5.2. SELinux 的运作模式: 组件, 安全性本文, domain/type
再次的重复说明一下,SELinux 是透过 MAC 的方式来控管程序,他控制的主体是程序, 而目标则是该程序能否读取的『档案资源』!所以先来说明一下这些咚咚的相关性!

  • 主体 (Subject): SELinux 主要想要管理的就是程序,因此你可以将『主体』跟本章谈到的 process 划上等号;
  • 目标 (Object): 主体程序能否存取的『目标资源』一般就是文件系统。因此这个目标项目可以同文件系统划上等号;
  • 政策 (Policy): 由于程序与档案数量庞大,因此 SELinux 会依据某些服务来制订基本的存取安全性政策。这些政策内还会有详细的规则 (rule) 来指定不同的服务开放某些资源的存取与否。在目前的 CentOS 5.x 里面仅有提供两个主要的政策,分别是:
    o targeted:针对网络服务限制较多,针对本机限制较少,是预设的政策;
    o strict:完整的 SELinux 限制,限制方面较为严格。
    建议使用预设的 targeted 政策即可。
  • 安全性本文 (security context): 我们刚刚谈到了主体、目标与政策面,但是主体能不能存取目标除了政策指定之外,主体与目标的安全性本文必须一致才能够顺利存取。 这个安全性本文 (security context) 有点类似文件系统的 rwx !安全性本文的内容与设定是非常重要的! 如果设定错误,你的某些服务(主体程序)就无法存取文件系统(目标资源),当然就会一直出现『权限不符』的错误讯息了!
    这里写图片描述
    上图的重点在『主体』如何取得『目标』的资源访问权限! 由上图我们可以发现,主体程序必须要通过 SELinux 政策内的规则放行后,就可以与目标资源进行安全性本文的比对, 若比对失败则无法存取目标,若比对成功则可以开始存取目标。问题是,最终能否存取目标还是与文件系统的 rwx 权限设定有关!如此一来,加入了 SELinux 之后,出现权限不符的情况时,你就得要一步一步的分析可能的问题了!

一、安全性本文 (Security Context)
CentOS 5.x 已经帮我们制订好非常多的规则了,这部份你只要知道如何开启/关闭某项规则的放行与否即可。 那个安全性本文比较麻烦!因为你可能需要自行配置文件案的安全性本文!为何需要自行设定啊? 举例来说,你不也常常进行档案的 rwx 的重新设定吗?这个安全性本文你就将他想成 SELinux 内必备的 rwx 就是了!
安全性本文存在于主体程序中与目标档案资源中。程序在内存内,所以安全性本文可以存入是没问题。 那档案的安全性本文是记录在哪里呢?事实上,安全性本文是放置到档案的 inode 内的,因此主体程序想要读取目标档案资源时,同样需要读取 inode , 这 inode 内就可以比对安全性本文以及 rwx 等权限值是否正确,而给予适当的读取权限依据。
那么安全性本文到底是什么样的存在呢?我们先来看看 /root 底下的档案的安全性本文好了。 观察安全性本文可使用『 ls -Z 』去观察如下:(注意:你必须已经启动了 SELinux 才行!若尚未启动,这部份请稍微看过一遍即可。底下会介绍如何启动 SELinux 喔!)
这里写图片描述
如上所示,安全性本文主要用冒号分为三个字段,这三个字段的意义为:
这里写图片描述
这三个字段的意义仔细的说明一下吧:

  1. 身份识别 (Identify):
    相当于账号方面的身份识别!主要的身份识别则有底下三种常见的类型:
    o root:表示 root 的账号身份,如同上面的表格显示的是 root 家目录下的数据!
    o system_u:表示系统程序方面的识别,通常就是程序;
    o user_u:代表的是一般使用者账号相关的身份。
    你会发现身份识别中,除了 root 之外,其他的识别后面都会加上『 _u 』的字样! 这个身份识别重点在让我们了解该数据为何种身份所有。 而系统上面大部分的数据都会是 system_u 或 root !至于如果是在 /home 底下的数据,那么大部分应该就会是 user_u !

  2. 角色 (Role):
    透过角色字段,我们可以知道这个数据是属于程序、档案资源还是代表使用者。一般的角色有:
    o object_r:代表的是档案或目录等档案资源,这应该是最常见的;
    o system_r: 代表的就是程序! 不过,一般使用者也会被指定成为 system_r !
    你也会发现角色的字段最后面使用『 _r 』来结尾!因为是 role 的意思!

  3. 类型 (Type) :
    (最重要!) 在预设的 targeted 政策中, Identify 与 Role 字段基本上是不重要的!重要的在于这个类型 (type) 字段! 基本上,一个主体程序能不能读取到这个档案资源,与类型字段有关!而类型字段在档案与程序的定义不太相同,分别是:
    o type:在档案资源 (Object) 上面称为类型 (Type);
    o domain:在主体程序 (Subject) 则称为领域 (domain) 了!
    domain 需要与 type 搭配,则该程序才能够顺利的读取档案资源!

二、程序与档案 SELinux type 字段的相关性
那么这三个字段如何利用呢?首先我们来瞧瞧主体程序在这三个字段的意义为何!透过身份识别与角色字段的定义, 我们可以约略知道某个程序所代表的意义!基本上,这些对应资料在 targeted 政策下的对应如下:
这里写图片描述
但就如上所述,其实最重要的字段是类型字段,主体与目标之间是否具有可以读写的权限,与程序的 domain 及档案的 type 有关!这两者的关系我们可以使用达成 WWW 服务器功能的 httpd 这支程序与 /var/www/html 这个网页放置的目录来说明。 首先,看看这两个咚咚的安全性本文内容:
这里写图片描述
httpd 属于 httpd_exec_t 这个可以执行的类型,而 /var/www/html 则属于 httpd_sys_content_t 这个可以让 httpd 领域 (domain) 读取的类型。文字看起来不太容易了解!我们使用图示来说明这两者的关系!
这里写图片描述
上图的意义我们可以这样看的:

  1. 首先,我们触发一个可执行的目标档案,那就是具有 httpd_exec_t 这个类型的 /usr/sbin/httpd 档案;
  2. 该档案的类型会让这个档案所造成的主体程序 (Subject) 具有 httpd 这个领域 (domain), 我们的政策针对这个领域已经制定了许多规则,其中包括这个领域可以读取的目标资源类型;
  3. 由于 httpd domain 被设定为可以读取 httpd_sys_content_t 这个类型的目标档案 (Object), 因此你的网页放置到 /var/www/html/ 目录下,就能够被 httpd 那支程序所读取了;
  4. 但最终能不能读到正确的资料,还得要看 rwx 是否符合 Linux 权限的规范!

上述的流程告诉我们几个重点,第一个是政策内需要制订详细的 domain/type 相关性;第二个是若档案的 type 设定错误, 那么即使权限设定为 rwx 全开的 777 ,该主体程序也无法读取目标档案资源的啦!不过如此一来, 也就可以避免用户将他的家目录设定为 777 时所造成的权限困扰。

17.5.3. SELinux 的启动、关闭与观察: getenforce, sestatus, 启动与关闭, setenforce
并非所有的 Linux distributions 都支持 SELinux 的,所以你必须要先观察一下你的系统版本为何! 这里介绍的 CentOS 5.x 本身就有支持 SELinux !所以你不需要自行编译 SELinux 到你的 Linux 核心中! 目前 SELinux 支持三种模式,分别如下:

  • enforcing:强制模式,代表 SELinux 运作中,且已经正确的开始限制 domain/type 了;
  • permissive:宽容模式:代表 SELinux 运作中,不过仅会有警告讯息并不会实际限制 domain/type 的存取。这种模式可以用来作为 SELinux 的 debug 之用;
  • disabled:关闭,SELinux 并没有实际运作。

那你怎么知道目前的 SELinux 模式呢?就透过 getenforce 吧!
这里写图片描述
另外,我们又如何知道 SELinux 的政策 (Policy) 为何呢?这时可以使用 sestatus 来观察:
这里写图片描述
如上所示,目前是启动的,而且是 Enforcing 模式,而由配置文件查询得知亦为 Enforcing 模式。 此外,目前的预设政策为 targeted 这一个。你应该要有疑问的是, SELinux 的配置文件是哪个档案啊? 其实就是 /etc/selinux/config 这个档案!我们来看看内容:
这里写图片描述
一、SELinux 的启动与关闭
上面是默认的政策与启动模式!你要注意的是,如果改变了政策则需要重新启动;如果由 enforcing 或 permissive 改成 disabled ,或由 disabled 改成其他两个,那也必须要重新启动。这是因为 SELinux 是整合到核心里面去的, 你只可以在 SELinux 运作下切换成为强制 (enforcing) 或宽容 (permissive) 模式,不能够直接关闭 SELinux 的! 同时,由 SELinux 关闭 (disable) 的状态到开启的状态也需要重新启动!所以,如果刚刚你发现 getenforce 出现 disabled 时, 请到上述档案修改成为 enforcing 吧!
所以,如果你要启动 SELinux 的话,请将上述的 SELINUX=enforcing 设定妥当,并且指定 SELINUXTYPE=targeted 这一个设定, 并且到 /boot/grub/menu.lst 这个档案去,看看核心有无关闭 SELinux 了。
这里写图片描述
请注意到上面特殊字体的那一行,确认 kernel 后面不可以接『 selinux=0 』这个项目!因为 selinux=0 指定给核心时, 则核心会自动的忽略 /etc/selinux/config 的设定值,而直接略过 SELinux 的加载,所以你的 SELinux 模式就会变成 disabled 了!因为我们要启动,所以这里得要确认不存在 selinux=0 才行! 如果一切设定妥当,接下来就是 reboot 重新启动!
不过你要注意的是,如果从 disable 转到启动 SELinux 的模式时, 由于系统必须要针对档案写入安全性本文的信息,因此开机过程会花费不少时间在等待重新写入 SELinux 安全性本文 (有时也称为 SELinux Label) ,而且在写完之后还得要再次的重新启动一次!你必须要等待粉长一段时间! 等到下次开机成功后,再使用 getenforce 或 sestatus 来观察看看有否成功的启动到 Enforcing 的模式!
如果你已经在 Enforcing 的模式,但是可能由于一些设定的问题导致 SELinux 让某些服务无法正常的运作, 此时你可以将 Enforcing 的模式改为宽容 (permissive) 的模式,让 SELinux 只会警告无法顺利联机的讯息, 而不是直接抵挡主体程序的读取权限。让 SELinux 模式在 enforcing 与 permissive 之间切换的方法为:
这里写图片描述
不过请注意, setenforce 无法在 Disabled 的模式底下进行模式的切换!

17.5.4. SELinux 网络服务运作范例: 启动 (ps -Z), 错误情况, 解决 (chcon, restorecon)
由于 CentOS 5.x 预设使用 targeted 这个政策,而这个政策主要是在管理网络服务,本机端的程序则比较不受 SELinux 的管制。 既然上头我们曾经举过 /usr/sbin/httpd 这个程序来当作范例,那么我们就使用 WWW 服务器来说明一下 SELinux 的运作方式吧。

一、网络服务的启动与观察
首先,让我们启动 httpd 这支服务!要记得的是,一般服务启动的脚本会在 /etc/init.d/ 底下, 所以我们可以这样启动与观察:
这里写图片描述
ps -Z 这个『 -Z 』的选项可以让我们查阅程序的安全性本文!其他相关的程序说明请自行查阅本章上面各节的内容。 我们可以发现这整个程序的 domain 是 httpd_t 这个咚咚!再来我们来处理一下首页的数据先。 由于首页是放置到 /var/www/html,且档名应该要是『 index.html 』,因此我们可以这样简单的制作首页:
这里写图片描述
接下来,如果你在浏览器上面输入『 http://127.0.0.1 』应该会看到如下的画面才对!
这里写图片描述
此时你的浏览器会透过 httpd 这个程序拥有的 httpd_t 这个 domain 去读取 /var/www/html/index.html 这个档案的! 先来看看这个档案的权限与 SELinux 的重点内容安全性本文数据:
这里写图片描述
权限是 apache 可以读取的 r 标志,而 SELinux 则是 httpd_sys_content_t 的类型 (type),也是 httpd_t 能读取的! 那么为何 httpd_t 可以读取呢?因为 targeted 政策里面有设定!关于政策设定的查询我们可以在后续跟大家作介绍, 这里先了解一下即可。

二、错误的SELinux 安全性本文
让我们来了解一下什么是错误的安全性本文设定好了!现在,我们将重要的网页数据在 root 的家目录底下制作! 设定如下:
这里写图片描述
等到上述的动作都做完后,如果在浏览器输入 http://127.0.0.1/index.html ,你应该会想到画面会出现我们想要的『 My 2nd web page…』才对,但是结果即变成:
这里写图片描述
记得要在网址列指定 index.html 否则出现的会变成欢迎首页的画面。而屏幕上出现的错误讯息是没有权限 (You don’t have permission…)。看看这个 /var/www/html/index.html 的权限吧!
这里写图片描述
你会发现,权限是对的 (apache 使用者依旧可以读取),但是安全性本文内容即是用户家目录! 真是要命!这个用户家目录默认可不能给 httpd_t 这个 domain 读取的!所以就产生错误!那该如何处置呢?

三、重设 SELinux 安全性本文
既然安全性本文是错的,怎么修改呢?可以透过两个指令!首先我们使用 chcon 来处理:
这里写图片描述
这里写图片描述
chcon 是透过直接指定的方式来处理安全性本文的类型资料。那我们知道其实系统默认的目录都有特殊的 SELinux 安全性本文, 举例来说, /var/www/html 原本就是 httpd 可以读取的目录!既然如此,那有没有可以使用预设的安全性本文来还原的方式? 有的,那就是 restorecon :
这里写图片描述

17.5.5. SELinux 所需的服务: setroubleshoot, sealert, auditd, audit2why
由于 SELinux 是整合到核心的一个核心功能,因此你几乎不需要启动什么额外的服务来开启 SELinux 的。 开机完成后, SELinux 就启动了。不过,你刚刚也发现到当我们复制或移动某些数据到特定的目录时, 可能由于没有注意到修改 SELinux 的安全性本文内容,结果导致网络服务无法顺利运行的问题! 有没有什么方法可以记录当发生 SELinux 错误时,将那些有用的信息记录下来,并且提供解决的方案呢? 此时就得要底下的几个服务的辅助!

一、setroubleshoot –> 错误讯息写入 /var/log/messages
几乎所有 SELinux 相关的程序都会以 se 为开头,这个服务也是以 se 为开头!而 troubleshoot 大家都知道是错误克服, 因此这个 setroubleshoot 自然就得要启动他!这个服务会将关于 SELinux 的错误讯息与克服方法记录到 /var/log/messages 里头,所以你一定得要启动这个服务才好。那如何在开机的时候就启动 setroubleshoot 呢?这样处理先:
这里写图片描述
这支服务预设几乎都会启动!除非你看到 3:off 或 5:off 时,才需要以『 chkconfig setroubleshoot on 』 去设定一下。那么如果有发生错误时,讯息像什么呢?我们刚刚不是以浏览器浏览 index.html 并导致错误吗? 那就将该错误捉来瞧瞧!
这里写图片描述
上面的错误讯息可是同一行!大纲说的是『SElinux 被用来避免 httpd 读取到错误的安全性本文, 想要查阅完整的数据,请执行 sealert -l 6c02…』!重点就是 sealert -l ! 上面提供的信息并不完整,想要更完整的说明得要靠 sealert 配合侦测到的错误代码来处理。 实际处理后会像这样:
这里写图片描述
重点就是上面特殊字体显示的地方!你只要照着『Allowing Access』里面的提示去进行处理, 就能够完成你的 SELinux 类型设定了!比对刚刚我们上个小节提到的 restorecon 与 chcon 你就能够知道, setroubleshoot 提供的讯息有多有效了吧!

二、auditd –> 详细资料写入 /var/log/audit/audit.log
audit 是稽核的意思,这个 auditd 会将 SELinux 发生的错误信息写入 /var/log/audit/audit.log 中! 与上个服务相同的,你最好在开机时就设定这服务为启动的模式,因此可以照样造句:
这里写图片描述
这里写图片描述
与 setroubleshoot 不同的是, auditd 会将许多的 SELinux 信息都记录下来,不只是错误讯息而已, 因此登录档 /var/log/audit/audit.log 非常的庞大!要直接到这档案里面去搜寻数据是挺累人的~ 还好,SELinux 有提供一个 audit2why 的指令来让我们查询错误讯息的回报!那么这个指令如何使用呢? 可以这样用的:
这里写图片描述
audit2why 的用法与输出结果如上,比较有趣的是那个 AVC ,AVC 是 access vector cache 的缩写, 目的是记录所有与 SELinux 有关的存取统计资料。输出的信息当中,会有谈到产生错误的问题为何,如上表特殊字体部分, 你会发现错误讯息主要告知 type 不符,所以导致错误的发生!不过,我个人觉得 setroubleshoot 比较好用! 这两个好东西都可以帮助你解决 SELinux 的错误,因此,请务必至少要学会其中一项错误分析的方法!

17.5.6. SELinux 的政策与规则管理: seinfo, sesearch, getsebool, setsebool, semanage
现在你应该知道,一个主体程序能否读取到目标档案资源的重点在于 SELinux 的政策以及政策内的各项规则, 然后再透过该规则的定义去处理各目标档案的安全性本文,尤其是『类型』的部分。现在我们也知道可以透过 sestatus 与 getenforce 去取得目前的 SELinux 状态。 但是,能不能知道更详细的政策说明与规则项目呢?底下我们就来了解了解!

一、政策查阅
CentOS 5.x 预设使用 targeted 政策,那么这个政策提供多少相关的规则呢?此时可以透过 seinfo 来查询!
这里写图片描述
这里写图片描述
从上面我们可以看到与 httpd 有关的布尔值,同样的,如果你想要找到有 httpd 字样的安全性本文类别时, 就可以使用『 seinfo -t | grep httpd 』来查询了!如果查询到相关的类别或者是布尔值后,想要知道详细的规则时, 就得要使用 sesearch 这个指令了!
这里写图片描述
这里写图片描述
你可以很轻易的查询到某个主体程序 (subject) 可以读取的目标档案资源 (Object) , 从我们上面的练习,我们也可以很轻松的就知道,为何 httpd_t 可以读取 httpd_sys_content_t ! 那如果是布尔值呢?里面又规范了什么?让我们来看看先:
这里写图片描述
从这个布尔值的设定我们可以看到里面规范了非常多的主体程序与目标档案资源的放行与否! 所以你知道了,实际规范这些规则的,就是布尔值的项目!那也就是我们之前所说的一堆规则是也! 你的主体程序能否对某些目标档案进行存取,与这个布尔直非常有关系!因为布尔值可以将规则设定为启动 (1) 或者是关闭 (0) !
由 seinfo 与 sesearch 的输出信息,我们也会得到实际的政策数据都是放置到 /etc/selinux/targeted/policy/ 底下, 事实上,所有与 targetd 相关的信息都是放置到 /etc/selinux/targeted 里面的!包括安全性本文相关的信息。 这部分等一下课到安全性本文的默认值修改时,我们再来讨论。

二、布尔值的查询与修改
上面我们透过 sesearch 知道了,其实 Subject 与 Object 能否有存取的权限,是与布尔值有关的, 那么系统有多少布尔值可以透过 seinfo -b 来查询,但,每个布尔值是启动的还是关闭的呢?这就来查询看看吧:
这里写图片描述
那么如果查询到某个布尔值,并且以 sesearch 知道该布尔值的用途后,想要关闭或启动他,又该如何处置?
这里写图片描述
这个 setsebool 最好记得一定要加上 -P 的选项!因为这样才能将此设定写入配置文件! 这是非常棒的工具组!你一定要知道如何使用 getsebool 与 setsebool 才行!

三、默认目录的安全性本文查询与修改
还记得我们在使用 restorecon 时谈到每个目录或档案都会有默认的安全性本文吗? 会制订目录的安全性本文,是因为系统的一些服务所放置档案的目录已经是确定的,当然有预设的安全性本文管理上较方便。 那你如何查询这些目录的默认安全性本文呢?就得要使用 semanage !
这里写图片描述
从上面的说明,我们知道其实 semanage 可以处理非常多的任务,不过,在这个小节我们主要想了解的是每个目录的默认安全性本文。 如上面范例一所示,我们可以查询的到每个目录的安全性本文!而目录的设定可以使用正规表示法去指定一个范围。那么如果我们想要增加某些自定义的目录的安全性本文呢? 举例来说,我想要制订 /srv/samba 成为 public_content_t 的类型时,应该如何指定呢?
这里写图片描述
这里写图片描述
这里写图片描述
semanage 的功能很多,不过这里主要用到的仅有 fcontext 这个项目的动作而已。如上所示, 你可以使用 semanage 来查询所有的目录默认值,也能够使用他来增加默认值的设定!

猜你喜欢

转载自blog.csdn.net/kk53976047/article/details/79344059
今日推荐