• 20220921 16. 程序管理与 SELinux 初探


    16.1 什么是程序 (process)

    在 Linux 系统当中:“触发任何一个事件时,系统都会将他定义成为一个程序,并且给予这个程 序一个 ID ,称为 PID,同时依据启发这个程序的使用者与相关属性关系,给予这个 PID 一组 有效的权限设置。” 从此以后,这个 PID 能够在系统上面进行的动作,就与这个 PID 的权限 有关了!

    16.1.1 程序与程序 (process & program)

    “执行一个程序或指令”就可以触发一个事件而 取得一个 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 对吧!那么,我们的 shell 是 bash 对吧,这个 bash 在 /bin/bash 对吧,那么同时间的每个人登陆都是执行 /bin/bash 对吧!不过,每个人取得的权限就是不 同!也就是说,我们可以这样看:

    程序与程序之间的差异

    当我们登陆并执行 bash 时,系统已经给我们一个 PID 了,这个 PID 就是依据登 陆者的 UID/GID (/etc/passwd) 来的

    /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 环境下,就 称为“父程序”了!

    程序相关系之示意图

    因为每个程序都有一个 PID ,那某个程序的父 程序该如何判断?就通过 Parent PID (PPID) 来判断即可。

    例题:请在目前的 bash 环境下,再触发一次 bash ,并以“ ps -l ”这个指令观察程序相关的输 出信息。

    F  S  UID   PID    PPID   C  PRI  NI ADDR SZ     WCHAN  TTY     TIME      CMD
    0  S  1000  13928  13927  0  80   0  -    29038  wait   pts/0   00:00:00  bash 
    0  S  1000  13970  13928  1  80   0  -    29033  wait   pts/0   00:00:00  bash 
    0  R  1000  14000  13970  0  80   0  -    30319  -      pts/0   00:00:00  ps
    

    第一个 bash 的 PID 与第二个 bash 的 PPID 都是 13928 啊, 因为第二个 bash 是来自于第一个所产生的嘛!

    很多朋友常常会发现:“咦!明明我将有问题的程序关闭了,怎么过一阵子他又自动的产生?

    如果不是 crontab 工作调度的影响,肯定有一支父程序存在,所以你杀掉子程序后, 父程序就会主动再 生一支!

    fork and exec:程序调用的流程

    在 Linux 的程序调用通常称为 fork-and-exec 的流程!程序都会借由父程序以复制 (fork) 的方式产生一个一模一样的子程序, 然后被复制出来的子程序再以 exec 的方式来执行实际 要进行的程序,最终就成为一个子程序的存在。

    程序使用 fork and exec 呼叫的情况示意图

    1. 系统先以 fork 的方式复制一个与父程序相同的暂存程序,这个程序与父程序唯一的差别 就是 PID 不同! 但是这个暂存程序还会多一个 PPID 的参数,就是父程序 的程序识别码

    2. 暂存程序开始以 exec 的方式载入实际要执行的程序,以上述图 示来讲,新的程序名称为 qqq ,最终子程序的程序码就会变成 qqq 了

    系统或网络服务:常驻在内存的程序

    常驻在内存当中的程序通常都是负责一些系统所提供的功能以服务使用者各项任务,因此这 些常驻程序就会被我们称为:服务 (daemon)

    Linux 希望我们可以简单的判断该程序是否为 daemon, 所以,一般 daemon 类型的程序都会加上 d 在文件名后头~包括服务器篇我们会看到的 httpd, vsftpd 等等都是

    16.1.2 Linux 的多用户多任务环境

    在 Linux 下面执行一个指令时,系统会将相关的权限、属性、程序码 与数据等均载入内存, 并给予这个单元一个程序识别码 (PID),最终该指令可以进行的任 务则与这个 PID 的权限有关。

    多人环境:

    什么是“多用户多任务”?在 Linux 系 统上面具有多种不同的帐号, 每种帐号都有都有其特殊的权限,只有一个人具有至高无上的 权力,那就是 root (系统管理员)。除了 root 之外,其他人都必须要受一些限制的!而每个 人进入 Linux 的环境设置都可以随着每个人的喜好来设置

    多任务行为:

    Linux 可以让 CPU 在各个工作间进行切换

    由于性能非常好,因此当多人同时登陆系统时,其实会感受 到整部主机好像就为了你存在一般! 这就是多用户多任务的环境

    多重登陆环境的七个基本终端窗口:

    在 Linux 当中,默认提供了六个文字界面登陆窗口,以及一个图形界面,每个终端机界面的登陆者还可以不同人

    特殊的程序管理行为:

    Linux 几乎可以说绝对不会死机的!因为他可以在任 何时候, 将某个被困住的程序杀掉,然后再重新执行该程序而不用重新开机!

    如果我在 Linux 下以文字界面登陆,在屏幕当中显示错误讯息后就挂了~动都不能动,该如 何是好!? 这个时候那默认的七个窗口就帮上忙啦!你可以随意的再按 [Alt]+[F1].....[F7] 来 切换到其他的终端机界面,然后以 ps -aux 找出刚刚的错误程序,然后给他 kill 一下,哈哈, 回到刚刚的终端机界面

    bash 环境下的工作管理 (job control)

    [root@study ~]# cp file1 file2 &
    

    & 的功能,他表示将 file1 这个文件复制为 file2 ,且放置于背 景中执行, 也就是说执行这一个命令之后,在这一个终端接口仍然可以做其他的工作!而当 这一个指令 (cp file1 file2) 执行完毕之后,系统将会在你的终端接口显示完成的消息

    多用户多任务的系统资源分配问题考虑:

    由于使用者日盛,当使用者达到一定的人数后, 通常你的机器便 需要升级了,因为 CPU 的运算与 RAM 的大小可能就会不敷使用

    16.2 工作管理 (job control)

    这个工作管理 (job control) 是用在 bash 环境下的,也就是说:“当我们登陆系统取得 bash shell 之后,在单一终端机接口下同时进行多个工作的行为管理 ”。

    16.2.1 什么是工作管理?

    进行工作管理的行为中, 其实每个工作都是目前 bash 的子程序,亦即彼此之间是有相关性的。 我们无法以 job control 的方式由 tty1 的环境 去管理 tty2 的 bash

    由于假设我们只有一个终端接口,因此在可以出现提示字符让你操作的环境就称为前景 (foreground),至于其他工作就可以让你放入背景 (background) 去暂停或运行。要注意 的是,放入背景的工作想要运行时, 他必须不能够与使用者互动。

    要进行 bash 的 job control 必须要注意到的限制是:

    • 这些工作所触发的程序必须来自于你 shell 的子程序(只管理自己的 bash);

    • 前景:你可以控制与下达指令的这个环境称为前景的工作 (foreground);

    • 背景:可以自行运行的工作,你无法使用 [ctrl]+c 终止他,可使用 bg/fg 调用该工作;

    • 背景中“执行”的程序不能等待 terminal/shell 的输入(input)

    16.2.2 job control 的管理

    bash 只能够管理自己的工作而不能管理其他 bash 的工作,所以即使你是 root 也 不能够将别人的 bash 下面的 job 给他拿过来执行。此外,又分前景与背景,然后在背景里面 的工作状态又可以分为“暂停 (stop)”与“运行中 (running)”

    直接将指令丢到背景中“执行”的 &

    [root@www ~]# tar -zpcf /tmp/etc.tar.gz /etc &
    [1] 8400  <== [job number] PID 
    [root@www ~]# tar: Removing leading `/' from member names 
    # 在中括号内的号码为工作号码 (job number),该号码与 bash 的控制有关。
    # 后续的 8400 则是这个工作在系统中的 PID。至於后续出现的数据是 tar 运行的数据流,
    # 由於我们没有加上数据流重导向,所以会影响画面!不过不会影响前景的操作喔!
    

    那么丢到背景中的工作什么时候完成?完成的时候会显示什么?如果你输 入几个指令后,突然出现这个数据:

    [1]+     Done         tar -zpcf /tmp/etc.tar.gz /etc
    

    就代表 [1] 这个工作已经完成 (Done)

    在背景当中执行的指令,如果有 stdout 及 stderr 时,他的数据依旧是输出到屏 幕上面的, 所以,我们会无法看到提示字符,当然也就无法完好的掌握前景工作。同时由于 是背景工作的 tar , 此时你怎么按下 [ctrl]+c 也无法停止屏幕被搞的花花绿绿的!所以啰,最 佳的状况就是利用数据流重导向, 将输出数据传送至某个文件中

    [root@study ~]# tar -zpcvf /tmp/etc.tar.gz /etc > /tmp/log.txt 2>&1 &
    

    如此一来,输出的信息都给他传送到 /tmp/log.txt 当中,当然就不会影响到我们前景的 作业了。

    将“目前”的工作丢到背景中“暂停”:[ctrl]-z

    [root@www ~]# vim ~/.bashrc
    # 在 vim 的一般模式下,按下 [ctrl]-z 这两个按键
    [1]+  Stopped                 vim ~/.bashrc
    [root@www ~]#   <==顺利取得了前景的操控权!
    [root@www ~]# find / -print
    ....(输出省略)....
    # 此时萤幕会非常的忙碌!因为萤幕上会显示所有的档名。请按下 [ctrl]-z 暂停
    [2]+  Stopped                 find / -print
    

    在 vim 的一般模式下,按下 [ctrl] 及 z 这两个按键,屏幕上会出现 [1] ,表示这是第一个工 作, 而那个 + 代表最近一个被丢进背景的工作,且目前在背景下默认会被取用的那个工作 (与 fg 这个指令有关 )!而那个 Stopped 则代表目前这个工作的状态。

    在默认的情况下, 使用 [ctrl]-z 丢到背景当中的工作都是“暂停”的状态喔!

    观察目前的背景工作状态: jobs

    [root@www ~]# jobs [-lrs]
    选项与参数:
    -l  :除了列出 job number 与命令串之外,同时列出 PID 的号码;
    -r  :仅列出正在背景 run 的工作;
    -s  :仅列出正在背景当中暂停 (stop) 的工作。
    
    范例一:观察目前的 bash 当中,所有的工作,与对应的 PID
    [root@www ~]# jobs -l
    [1]- 10314 Stopped                 vim ~/.bashrc
    [2]+ 10833 Stopped                 find / -print
    

    那个 + 代表默认的取用工作。 所以 说:“目前我有两个工作在背景当中,两个工作都是暂停的, 而如果我仅输入 fg 时,那么那 个 [2] 会被拿到前景当中来处理”!

    其实 + 代表最近被放到背景的工作号码, - 代表最近最后第二个被放置到背景中的工作号 码。 而超过最后第三个以后的工作,就不会有 +/- 符号存在了!

    将背景工作拿到前景来处理:fg

    [root@www ~]# fg %jobnumber
    选项与参数:
    %jobnumber :jobnumber 为工作号码(数字)。注意,那个 % 是可有可无的!
    
    范例一:先以 jobs 观察工作,再将工作取出:
    [root@www ~]# jobs
    [1]- 10314 Stopped                 vim ~/.bashrc
    [2]+ 10833 Stopped                 find / -print
    [root@www ~]# fg      <==默认取出那个 + 的工作,亦即 [2]。立即按下[ctrl]-z
    [root@www ~]# fg %1   <==直接规定取出的那个工作号码!再按下[ctrl]-z
    [root@www ~]# jobs
    [1]+  Stopped                 vim ~/.bashrc
    [2]-  Stopped                 find / -print
    

    输入“ fg - ” 则代表将 - 号的那个工作号码拿出 来,输入 fg + 等同于 fg

    让工作在背景下的状态变成运行中: bg

    范例一:一运行 find / -perm +7000 > /tmp/text.txt 后,立刻丢到背景去暂停!
    [root@www ~]# find / -perm +7000 > /tmp/text.txt
    # 此时,请立刻按下 [ctrl]-z 暂停!
    [3]+  Stopped                 find / -perm +7000 > /tmp/text.txt
    
    
    范例二:让该工作在背景下进行,并且观察他!!
    [root@www ~]# jobs ; bg %3 ; jobs
    [1]-  Stopped                 vim ~/.bashrc
    [2]   Stopped                 find / -print
    [3]+  Stopped                 find / -perm +7000 > /tmp/text.txt
    [3]+ find / -perm +7000 > /tmp/text.txt &  <==用 bg%3 的情况!
    [1]+  Stopped                 vim ~/.bashrc
    [2]   Stopped                 find / -print
    [3]-  Running                 find / -perm +7000 > /tmp/text.txt &
    

    管理背景当中的工作: kill

    给予该 工作一个讯号 (signal)

    [root@www ~]# kill -signal %jobnumber
    [root@www ~]# kill -l
    选项与参数:
    -l  :这个是 L 的小写,列出目前 kill 能够使用的讯号 (signal) 有哪些?
    signal :代表给予后面接的那个工作什么样的指示罗!用 man 7 signal 可知:
      -1 :重新读取一次参数的配置档 (类似 reload);
      -2 :代表与由键盘输入 [ctrl]-c 同样的动作;
      -9 :立刻强制删除一个工作;
      -15:以正常的程序方式终止一项工作。与 -9 是不一样的。
    
    范例一:找出目前的 bash 环境下的背景工作,并将该工作『强制删除』。
    [root@www ~]# jobs
    [1]+  Stopped                 vim ~/.bashrc
    [2]   Stopped                 find / -print
    [root@www ~]# kill -9 %2; jobs
    [1]+  Stopped                 vim ~/.bashrc
    [2]   Killed                  find / -print
    # 再过几秒你再下达 jobs 一次,就会发现 2 号工作不见了!因为被移除了!
    
    范例:找出目前的 bash 环境下的背景工作,并将该工作『正常终止』掉。
    [root@www ~]# jobs
    [1]+  Stopped                 vim ~/.bashrc
    [root@www ~]# kill -SIGTERM %1
    # -SIGTERM 与 -15 是一样的!您可以使用 kill -l 来查阅!
    

    -9 这个 signal 通常是用在“强制删除一个不正常的工作”时所使用的, -15 则 是以正常步骤结束一项工作(15也是默认值)

    killall 也是同样的用法

    signal 除了以 数值来表示之外,也可以使用讯号名称,使用 kill -l 查看 signal number 与名称的对应

    kill 后面接的数字默认会是 PID ,如果想要管理 bash 的工作控制,就得要加上 %数字 了

    16.2.3 离线管理问题

    在工作管理当中提到的“背景”指的是在终端机模式下可以避免 [crtl]-c 中断 的一个情境, 你可以说那个是 bash 的背景,并不是放到系统的背景去

    如果你是以远端连线方式连接到你的 Linux 主机,并且将工作以 & 的方式放到背景去, 请问,在工作尚未结束的情况下你离线了,该工 作还会继续进行吗?答案是“否”!不会继续进行,而是会被中断掉。

    如果我的工作需要进行一大段时间,我又不能放置在背景下面,那该如何处理 呢?

    at 是将工作放置到系统背景, 而与终 端机无关。如果不想要使用 at 的话,那你也可以尝试使用 nohup 这个指令来处理

    [root@www ~]# nohup [命令与参数]   <==在终端机前景中工作
    [root@www ~]# nohup [命令与参数] & <==在终端机背景中工作
    

    nohup 并不支持 bash 内置的指令,因此你 的指令必须要是外部指令才行

    # 1. 先编辑一支会『睡著 500 秒』的程序:
    [root@www ~]# vim sleep500.sh
    #!/bin/bash
    /bin/sleep 500s
    /bin/echo "I have slept 500 seconds."
    
    # 2. 丢到背景中去运行,并且立刻注销系统:
    [root@www ~]# chmod a+x sleep500.sh
    [root@www ~]# nohup ./sleep500.sh &
    [1] 5074
    [root@www ~]# nohup: appending output to ‘nohup.out’ <==会告知这个信息!
    [root@www ~]# exit
    

    由于我们的程序最后会输出一个讯息,但是 nohup 与 终端机其实无关了, 因此这个讯息的输出就会被导向“ ~/nohup.out ”

    如果你想要让在背景的工作在你登出后还能够继续的执行,那么使用 nohup 搭配 & 是不错的 运行情境

    16.3 程序管理

    16.3.1 程序的观察

    如何查阅系统上面正在运行当中的程序呢?利用静 态的 ps 或者是动态的 top,还能以 pstree 来查阅程序树之间的关系

    ps :将某个时间点的程序运行情况撷取下来

    [root@www ~]# ps aux  <==观察系统所有的程序数据
    [root@www ~]# ps -lA  <==也是能够观察所有系统的数据
    [root@www ~]# ps axjf <==连同部分程序树状态
    选项与参数:
    -A  :所有的 process 均显示出来,与 -e 具有同样的效用;
    -a  :不与 terminal 有关的所有 process ;
    -u  :有效使用者 (effective user) 相关的 process ;
    x   :通常与 a 这个参数一起使用,可列出较完整资讯。
    
    输出格式规划:
    l   :较长、较详细的将该 PID 的的资讯列出;
    j   :工作的格式 (jobs format)
    -f  :做一个更为完整的输出。
    

    通常鸟哥都会建议你,直接背两个比较不同的选项, 一个是只能查阅自己 bash 程序的“ ps -l ”一个则是可以查阅所有系统运行的程序“ ps aux ”!注意,你没看错,是“ ps aux ”没有那 个减号 (-)

    仅观察自己的 bash 相关程序: ps -l

    范例一:将目前属於您自己这次登陆的 PID 与相关资讯列示出来(只与自己的 bash 有关)
    [root@www ~]# ps -l
    F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
    4 S     0 13639 13637  0  75   0 -  1287 wait   pts/1    00:00:00 bash
    4 R     0 13700 13639  0  77   0 -  1101 -      pts/1    00:00:00 ps
    
    • F:代表这个程序旗标 (process flags),说明这个程序的总结权限,常见号码有:

      • 若为 4 表示此程序的权限为 root ;
      • 若为 1 则表示此子程序仅进行复制(fork)而没有实际运行(exec)。
    • S:代表这个程序的状态 (STAT),主要的状态有:

      • R (Running):该程序正在运行中;
      • S (Sleep):该程序目前正在睡眠状态(idle),但可以被唤醒(signal)。
      • D :不可被唤醒的睡眠状态,通常这支程序可能在等待 I/O 的情况(ex>列印)
      • T :停止状态(stop),可能是在工作控制(背景暂停)或除错 (traced) 状态;
      • 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 aux

    范例二:列出目前所有的正在内存当中的程序:
    [root@www ~]# ps aux
    USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    root         1  0.0  0.0   2064   616 ?        Ss   Mar11   0:01 init [5]
    root         2  0.0  0.0      0     0 ?        S<   Mar11   0:00 [migration/0]
    root         3  0.0  0.0      0     0 ?        SN   Mar11   0:00 [ksoftirqd/0]
    .....(中间省略).....
    root     13639  0.0  0.2   5148  1508 pts/1    Ss   11:44   0:00 -bash
    root     14232  0.0  0.1   4452   876 pts/1    R+   15:52   0:00 ps aux
    root     18593  0.0  0.0   2240   476 ?        Ss   Mar14   0:00 /usr/sbin/atd
    
    • 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 的顺序来排序显示

    范例三:以范例一的显示内容,显示出所有的程序:
    [root@www ~]# ps -lA
    
    范例四:列出类似程序树的程序显示:
    [root@www ~]# ps axjf
    

    还可以使用 pstree 来达成这个程序树

    范例五:找出与 cron 与 syslog 这两个服务有关的 PID 号码?
    [root@www ~]# ps aux | egrep '(cron|syslog)'
    

    僵尸 (zombie) 程序的成因 是因为该程序应该已经执行完毕,或者是因故应该要终止了, 但是该程序的父程序却无法完 整的将该程序结束掉,而造成那个程序一直存在内存当中。 如果你发现在某个程序的 CMD 后面还接上 <defunct> 时,就代表该程序是僵尸程序

    当系统不稳定的时候就容易造成所谓的僵尸程序,可能是因为程序写的不好啦,或者是使用 者的操作习惯不良等等所造成。 如果你发现系统中很多僵尸程序时,记得啊!要找出该程序 的父程序,然后好好的做个追踪,好好的进行主机的环境最优化啊! 看看有什么地方需要改 善的,不要只是直接将他 kill 掉而已呢!

    事实上,通常僵尸程序都已经无法控管,而直接是交给 systemd 这支程序来负责了,偏偏 systemd 是系统第一支执行的程序, 他是所有程序的父程序!我们无法杀掉该程序的 (杀掉 他,系统就死掉了!),所以啰,如果产生僵尸程序, 而系统过一阵子还没有办法通过核心 非经常性的特殊处理来将该程序删除时,那你只好通过 reboot 的方式来将该程序抹去了!

    top:动态观察程序的变化

    [root@www ~]# top [-d 数字] | top [-bnp]
    选项与参数:
    -d  :后面可以接秒数,就是整个程序画面升级的秒数。默认是 5 秒;
    -b  :以批量的方式运行 top ,还有更多的参数可以使用喔!
          通常会搭配数据流重导向来将批量的结果输出成为文件。
    -n  :与 -b 搭配,意义是,需要进行几次 top 的输出结果。
    -p  :指定某些个 PID 来进行观察监测而已。
    在 top 运行过程当中可以使用的按键命令:
        ? :显示在 top 当中可以输入的按键命令;
        P :以 CPU 的使用资源排序显示;
        M :以 Memory 的使用资源排序显示;
        N :以 PID 来排序喔!
        T :由该 Process 使用的 CPU 时间累积 (TIME+) 排序。
        k :给予某个 PID 一个讯号  (signal)
        r :给予某个 PID 重新制订一个 nice 值。
        q :离开 top 软件的按键。
    
    范例一:每两秒钟升级一次 top ,观察整体资讯:
    [root@www ~]# top -d 2
    top - 17:03:09 up 7 days, 16:16,  1 user,  load average: 0.00, 0.00, 0.00
    Tasks:  80 total,   1 running,  79 sleeping,   0 stopped,   0 zombie
    Cpu(s):  0.5%us,  0.5%sy,  0.0%ni, 99.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
    Mem:    742664k total,   681672k used,    60992k free,   125336k buffers
    Swap:  1020088k total,       28k used,  1020060k free,   311156k cached
        <==如果加入 k 或 r 时,就会有相关的字样出现在这里喔!
      PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND     
    14398 root      15   0  2188 1012  816 R  0.5  0.1   0:00.05 top
        1 root      15   0  2064  616  528 S  0.0  0.1   0:01.38 init
        2 root      RT  -5     0    0    0 S  0.0  0.0   0:00.00 migration/0
        3 root      34  19     0    0    0 S  0.0  0.0   0:00.00 ksoftirqd/0
    
    • 第一行(top...):这一行显示的资讯分别为:

      • 目前的时间,亦即是 17:03:09 那个项目;

      • 启动到目前为止所经过的时间,亦即是 up 7days, 16:16 那个项目;

      • 已经登陆系统的使用者人数,亦即是 1 user项目;

      • 系统在 1, 5, 15 分钟的平均工作负载。代表的是 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) 作为排序

    范例二:将 top 的资讯进行 2 次,然后将结果输出到 /tmp/top.txt
    [root@www ~]# top -b -n 2 > /tmp/top.txt
    
    范例三:我们自己的 bash PID 可由 $$ 变量取得,请使用 top 持续观察该 PID
    [root@www ~]# echo $$
    13639  <==就是这个数字!他是我们 bash 的 PID
    [root@www ~]# top -d 2 -p 13639
    

    pstree

    [root@www ~]# pstree [-A|U] [-up]
    选项与参数:
    -A  :各程序树之间的连接以 ASCII 字节来连接;
    -U  :各程序树之间的连接以万国码的字节来连接。在某些终端介面下可能会有错误;
    -p  :并同时列出每个 process 的 PID;
    -u  :并同时列出每个 process 的所属帐号名称。
    
    范例一:列出目前系统上面所有的程序树的相关性:
    [root@www ~]# pstree -A
    
    范例二:承上题,同时秀出 PID 与 users 
    [root@www ~]# pstree -Aup
    # 在括号 () 内的即是 PID 以及该程序的 owner 喔!不过,由於我是使用 
    # root 的身份运行此一命令,所以属於 root 的程序就不会显示出来啦!
    

    由 pstree 的输出我们也可以很清楚的知道,所有的程序都是依附在 systemd 这支程序下面 的! 仔细看一下,这支程序的 PID 是一号喔!因为他是由 Linux 核心所主动调用的第一支程 序!所以 PID 就是一号了。 这也是我们刚刚提到僵尸程序时有提到,为啥发生僵尸程序需要 重新开机? 因为 systemd 要重新启动,而重新启动 systemd 就是 reboot 啰!

    16.3.2 程序的管理

    程序是如何互 相管理的呢?其实是通过给予该程序一个讯号 (signal) 去告知该程序你想要让她作什么!

    可以使用 kill -l (小写的 L ) 或者是 man 7 signal 都可以查询到有多少 signal

    代号 名称 内容
    1 SIGHUP 启动被终止的程序,可让该 PID 重新读取自己的配置档,类似重新启动
    2 SIGINT 相当於用键盘输入 [ctrl]-c 来中断一个程序的进行
    9 SIGKILL 代表强制中断一个程序的进行,如果该程序进行到一半, 那么尚未完成的部分可能会有『半产品』产生,类似 vim会有 .filename.swp 保留下来。
    15 SIGTERM 以正常的结束程序来终止该程序。由於是正常的终止, 所以后续的动作会将他完成。不过,如果该程序已经发生问题,就是无法使用正常的方法终止时, 输入这个 signal 也是没有用的。
    19 SIGSTOP 相当於用键盘输入 [ctrl]-z 来暂停一个程序的进行

    一般来说,你只要记 得“1, 9, 15”这三个号码的意义即可。那么我们如何传送一个讯号给某个程序呢?就通过 kill 或 killall

    kill -signal PID

    例题:以 ps 找出 rsyslogd 这个程序的 PID 后,再使用 kill 传送讯息,使得 rsyslogd 可以重 新读取配置文件。

    找出 rsyslogd 的 PID 可以是这样做:

    ps aux | grep 'syslog' | grep -v 'grep'| awk '{print $2}'
    

    使用 kill -1 PID

    kill -SIGHUP $(ps aux|grep 'syslog'|grep -v 'grep'|awk '{print $2}')
    

    killall -signal 指令名称

    [root@www ~]# killall [-iIe] [command name]
    选项与参数:
    -i  :interactive 的意思,互动式的,若需要删除时,会出现提示字节给使用者;
    -e  :exact 的意思,表示『后面接的 command name 要一致』,但整个完整的命令
          不能超过 15 个字节。
    -I  :命令名称(可能含参数)忽略大小写。
    
    范例一:给予 syslogd 这个命令启动的 PID 一个 SIGHUP 的讯号
    [root@www ~]# killall -1 syslogd
    # 如果用 ps aux 仔细看一下,syslogd 才是完整的命令名称。但若包含整个参数,
    # 则 syslogd -m 0 才是完整的呢!
    
    范例二:强制终止所有以 httpd 启动的程序
    [root@www ~]# killall -9 httpd
    
    范例三:依次询问每个 bash 程序是否需要被终止运行!
    [root@www ~]# killall -i -9 bash
    Kill bash(16905) ? (y/N) n <==这个不杀!
    Kill bash(17351) ? (y/N) y <==这个杀掉!
    # 具有互动的功能!可以询问你是否要删除 bash 这个程序。要注意,若没有 -i 的参数,
    # 所有的 bash 都会被这个 root 给杀掉!包括 root 自己的 bash 喔!
    

    要删除某个程序,我们可以使用 PID 或者是启动该程序的指令名称, 而如果要删除某 个服务呢?最简单的方法就是利用 killall , 因为他可以将系统当中所有以某个指令名 称启动的程序全部删除

    16.3.3 关于程序的执行顺序

    如果所 有的程序同时被唤醒,那么 CPU 应该要先处理那个程序呢?这就得要考虑到程序的优先执行序 (Priority) 与 CPU 调度

    Priority 与 Nice 值

    Linux 给予程序一个所谓的“优先执行序 (priority, PRI)”, 这个 PRI 值越低代表越优先的意思。不过这个 PRI 值是由核心动态调 整的, 使用者无法直接调整 PRI 值的

    由于 PRI 是核心动态调整的,我们使用者也无权去干涉 PRI !那如果你想要调整程序的优先 执行序时,就得要通过 Nice 值(NI)了

    PRI(new) = PRI(old) + nice
    

    nice 值是有正负的

    • nice 值可调整的范围为 -20 ~ 19 ;

    • root 可随意调整自己或他人程序的 Nice 值,且范围为 -20 ~ 19 ;

    • 一般使用者仅可调整自己程序的 Nice 值,且范围仅为 0 ~ 19 (避免一般用户抢占系统资源);

    • 一般使用者仅可将 nice 值越调越高,例如本来 nice 为 5 ,则未来仅能调整到大于 5;

    如何给予 某个程序 nice 值呢?

    • 一开始执行程序就立即给予一个特定的 nice 值:用 nice 指令;

    • 调整某个已经存在的 PID 的 nice 值:用 renice 指令。

    nice :新执行的指令即给予新的 nice 值

    [root@www ~]# nice [-n 数字] command
    选项与参数:
    -n  :后面接一个数值,数值的范围 -20 ~ 19。
    
    范例一:用 root 给一个 nice 值为 -5 ,用於运行 vi ,并观察该程序!
    [root@www ~]# nice -n -5 vi &
    [1] 18676
    [root@www ~]# ps -l
    F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
    4 S     0 18625 18623  0  75   0 -  1514 wait   pts/1    00:00:00 bash
    4 T     0 18676 18625  0  72  -5 -  1242 finish pts/1    00:00:00 vi
    4 R     0 18678 18625  0  77   0 -  1101 -      pts/1    00:00:00 ps
    # 原本的 bash PRI 为 75  ,所以 vi 默认应为 75。不过由於给予 nice  为 -5 ,
    # 因此 vi 的 PRI 降低了!但并非降低到 70 ,因为核心还会动态调整!
    
    [root@www ~]# kill -9 %1 <==测试完毕将 vi 关闭
    

    举例来说,系统的背景工作中, 某些比较不重要的程序之进 行:例如备份工作!由于备份工作相当的耗系统资源, 这个时候就可以将备份的指令之 nice 值调大一些,可以使系统的资源分配的更为公平!

    renice :已存在程序的 nice 重新调整

    [root@www ~]# renice [number] PID
    选项与参数:
    PID :某个程序的 ID 啊!
    
    范例一:找出自己的 bash PID ,并将该 PID 的 nice 调整到 10
    [root@www ~]# ps -l
    F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
    4 S     0 18625 18623  0  75   0 -  1514 wait   pts/1    00:00:00 bash
    4 R     0 18712 18625  0  77   0 -  1102 -      pts/1    00:00:00 ps
    
    [root@www ~]# renice 10 18625
    18625: old priority 0, new priority 10
    
    [root@www ~]# ps -l
    F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
    4 S     0 18625 18623  0  85  10 -  1514 wait   pts/1    00:00:00 bash
    4 R     0 18715 18625  0  87  10 -  1102 -      pts/1    00:00:00 ps
    

    除了 renice 之外,top 同样的也是可以调整 nice 值的

    16.3.4 系统资源的观察

    free :观察内存使用情况

    [root@www ~]# free [-b|-k|-m|-g] [-t]
    选项与参数:
    -b  :直接输入 free 时,显示的单位是 Kbytes,我们可以使用 b(bytes), m(Mbytes)
          k(Kbytes), 及 g(Gbytes) 来显示单位喔!
    -t  :在输出的最终结果,显示实体内存与 swap 的总量。
    
    范例一:显示目前系统的内存容量
    [root@VM-72-146-centos ~/hwj]# free -m
                  total        used        free      shared  buff/cache   available
    Mem:           2848         346        1794           8         706        2263
    Swap:          1023           0        1023  
    

    Mem 那一行显示的是实体内存的量, Swap 则是内存交换空间的量

    total 是总量, used 是已被使用的量, free 则是剩余可用的 量。 后面的 shared/buffers/cached 则是在已被使用的量当中,用来作为缓冲及高速缓存的 量,这些 shared/buffers/cached 的用量中,在系统比较忙碌时, 可以被释出而继续利用!因 此后面就有一个 available (可用的) 数值

    系统 是“很有效率的将所有的内存用光光”,目的是为了让系统的存取性能加速

    需要注意的反而是 swap 的量。一般来说, swap 最好不要被使用,尤其 swap 最好不要被使用超过 20% 以上, 如果您发现 swap 的用量超过 20% ,那么,最好还是 买实体内存来插吧! 因为, Swap 的性能跟实体内存实在差很多,而系统会使用到 swap , 绝对是因为实体内存不足了才会这样做的

    Linux 系统为了要加速系统性能,所以会将最常使用到的或者是最近使用到的文件数据 高速缓存 (cache) 下来, 这样未来系统要使用该文件时,就直接由内存中搜寻取出,而不 需要重新读取硬盘,速度上面当然就加快了! 因此,实体内存被用光是正常的喔!

    uname:查阅系统与核心相关信息

    [root@www ~]# uname [-asrmpi]
    选项与参数:
    -a  :所有系统相关的资讯,包括底下的数据都会被列出来;
    -s  :系统核心名称
    -r  :核心的版本
    -m  :本系统的硬件名称,例如 i686 或 x86_64 等;
    -p  :CPU 的类型,与 -m 类似,只是显示的是 CPU 的类型!
    -i  :硬件的平台 (ix86)
    

    uptime:观察系统启动时间与工作负载

    显示出目前系统已经开机多久的时间,以及 1, 5, 15 分钟的平均负载

    uptime 可以显示出 top 画面的最上面一行

    netstat :追踪网络或插槽档

    netstat 的输出分为两大部分, 分别是网络与系统自己的程序相关性部分

    [root@www ~]# netstat -[atunlp]
    选项与参数:
    -a  :将目前系统上所有的连线、监听、Socket 数据都列出来
    -t  :列出 tcp 网络封包的数据
    -u  :列出 udp 网络封包的数据
    -n  :不以程序的服务名称,以埠号 (port number) 来显示;
    -l  :列出目前正在网络监听 (listen) 的服务;
    -p  :列出该网络服务的程序 PID 
    
    范例一:列出目前系统已经创建的网络连线与 unix socket 状态
    [root@www ~]# netstat
    Active Internet connections (w/o servers) <==与网络较相关的部分
    Proto Recv-Q Send-Q Local Address        Foreign Address      State
    tcp        0    132 192.168.201.110:ssh  192.168.:vrtl-vmf-sa ESTABLISHED
    Active UNIX domain sockets (w/o servers)  <==与本机的程序自己的相关性(非网络)
    Proto RefCnt Flags       Type       State         I-Node Path
    unix  20     [ ]         DGRAM                    9153   /dev/log
    unix  3      [ ]         STREAM     CONNECTED     13317  /tmp/.X11-unix/X0
    unix  3      [ ]         STREAM     CONNECTED     13233  /tmp/.X11-unix/X0
    unix  3      [ ]         STREAM     CONNECTED     13208  /tmp/.font-unix/fs7100
    

    两个部分,分别是网络的连线以及 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 封包的连线,远端的 172.16.220.234:48300 连线到本地端的 172.16.15.100:ssh ,这条连线状态是创建 (ESTABLISHED) 的状态

    除了网络上的连线之外,其实 Linux 系统上面的程序是可以接收不同程序所发送来的信息, 那就是 Linux 上头的插槽档 (socket file)

    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 指向的就是这些程序要交换数据的插槽文件啰!

    范例二:找出目前系统上已在监听的网络连线及其 PID
    [root@www ~]# netstat -tlnp
    Active Internet connections (only servers)
    Proto Recv-Q Send-Q Local Address    Foreign Address  State   PID/Program name
    tcp        0      0 127.0.0.1:2208   0.0.0.0:*        LISTEN  4566/hpiod
    tcp        0      0 0.0.0.0:111      0.0.0.0:*        LISTEN  4328/portmap
    tcp        0      0 127.0.0.1:631    0.0.0.0:*        LISTEN  4597/cupsd
    tcp        0      0 0.0.0.0:728      0.0.0.0:*        LISTEN  4362/rpc.statd
    tcp        0      0 127.0.0.1:25     0.0.0.0:*        LISTEN  4629/sendmail: 
    tcp        0      0 127.0.0.1:2207   0.0.0.0:*        LISTEN  4571/python
    tcp        0      0 :::22            :::*             LISTEN  4586/sshd
    # 除了可以列出监听网络的介面与状态之外,最后一个栏位还能够显示此服务的
    # PID 号码以及程序的命令名称喔!例如最后一行的 4586 就是该 PID
    
    范例三:将上述的本地端 127.0.0.1:631 那个网络服务关闭的话?
    [root@www ~]# kill -9 4597
    [root@www ~]# killall -9 cupsd
    

    dmesg :分析核心产生的讯息

    系统在开机的时候,核心会去侦测系统的硬件,你的某些硬件到底有没有被捉到,那就与这 个时候的侦测有关

    所有核心侦测的讯息,不管是开机时候还是系统运行过程中,反正只要是核心产生的讯息, 都会被记录到内存中的某个保护区段。 dmesg 这个指令就能够将该区段的讯息读出来的!

    范例一:输出所有的核心启动时的资讯
    [root@www ~]# dmesg | more
    
    范例二:搜寻启动的时候,硬盘的相关资讯为何?
    [root@www ~]# dmesg | grep -i hd
        ide0: BM-DMA at 0xd800-0xd807, BIOS settings: hda:DMA, hdb:DMA
        ide1: BM-DMA at 0xd808-0xd80f, BIOS settings: hdc:pio, hdd:pio
    hda: IC35L040AVER07-0, ATA DISK drive
    hdb: ASUS DRW-2014S1, ATAPI CD/DVD-ROM drive
    hda: max request size: 128KiB
    ....(底下省略)....
    

    vmstat :侦测系统资源变化

    vmstat 可以 侦测“ CPU / 内存 / 磁盘输入输出状态 ”等等,如果你想要了解一部繁忙的系统到底是哪个环 节最累人, 可以使用 vmstat 分析看看

    [root@www ~]# vmstat [-a] [延迟 [总计侦测次数]] <==CPU/内存等资讯
    [root@www ~]# vmstat [-fs]                      <==内存相关
    [root@www ~]# vmstat [-S 单位]                  <==配置显示数据的单位
    [root@www ~]# vmstat [-d]                       <==与磁碟有关
    [root@www ~]# vmstat [-p 分割槽]                <==与磁碟有关
    选项与参数:
    -a  :使用 inactive/active(活跃与否) 取代 buffer/cache 的内存输出资讯;
    -f  :启动到目前为止,系统复制 (fork) 的程序数;
    -s  :将一些事件 (启动至目前为止) 导致的内存变化情况列表说明;
    -S  :后面可以接单位,让显示的数据有单位。例如 K/M 取代 bytes 的容量;
    -d  :列出磁碟的读写总量统计表
    -p  :后面列出分割槽,可显示该分割槽的读写总量统计表
    
    范例一:统计目前主机 CPU 状态,每秒一次,共计三次!
    [root@VM-72-146-centos ~/hwj]# vmstat 1 3
    procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
     r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
     0  0      0 8737668 796796 3833392    0    0     0     9    0    0  1  0 99  0  0
     1  0      0 8736904 796796 3833424    0    0     0    52 1445 1634  1  0 99  0  0
     0  0      0 8736904 796796 3833428    0    0     0     0 1212 1490  0  0 100  0  0
    
    • 程序字段 (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 以后才支持)。

    范例二:系统上面所有的磁碟的读写状态
    [root@www ~]# vmstat -d
    

    16.4 特殊文件与程序

    特殊权限的 SUID/SGID/SBIT 对于你的“程序”是如何影响 的?

    16.4.1 具有 SUID/SGID 权限的指令执行状态

    • SUID 权限仅对二进制程序(binary program)有效;

    • 执行者对于该程序需要具有 x 的可执行权限;

    • 本权限仅在执行该程序的过程中有效 (run-time);

    • 执行者将具有该程序拥有者 (owner) 的权限。

    整个 SUID 的权限会生效是由于“具有该权限的程序被触发

    为啥执行了 passwd 后你就具有 root 的权限呢?不都是一般使用者执行的吗? 这是因为你在触发 passwd 后,会取得一个新的程序与 PID,该 PID 产生时通过 SUID 来给予该 PID 特殊的权限设置

    [dmtsai@www ~]$ passwd
    Changing password for user dmtsai.
    Changing password for dmtsai
    (current) UNIX password: <==这里按下 [ctrl]-z 并且按下 [enter]
    [1]+  Stopped                 passwd
    
    [dmtsai@www ~]$ pstree -u
    init-+-acpid
    ....(中间省略)....
         |-sshd---sshd---sshd(dmtsai)---bash-+-more
         |                                   |-passwd(root)
         |                                   `-pstree
    ....(底下省略)....
    
    # 查询整个系统的 SUID/SGID 的文件
    find / -perm /6000
    

    16.4.2 /proc/* 代表的意义

    所谓的程序都是在内存当中嘛!而内存当中的数据又都是写入到 /proc/* 这个目录下的

    目前主机上面的各个程序的 PID 都是以目录的型态存在于 /proc 当中。 举例来说, 我们开机所执行的第一支程序 systemd 他的 PID 是 1 , 这个 PID 的所有相关信息都写入在 /proc/1/* 当中!

    比较有趣的其实是两个文件,分别是:

    • cmdline:这个程序被启动的指令串;

    • environ:这个程序的环境变量内容。

    如 果是针对整个 Linux 系统相关的参数呢?那就是在 /proc 目录下面的文件

    档名 文件内容
    /proc/cmdline 加载 kernel 时所下达的相关参数!查阅此文件,可了解系统是如何启动的!
    /proc/cpuinfo 本机的 CPU 的相关资讯,包含时脉、类型与运算功能等
    /proc/devices 这个文件记录了系统各个主要装置的主要装置代号,与 mknod 有关呢!
    /proc/filesystems 目前系统已经加载的文件系统罗!
    /proc/interrupts 目前系统上面的 IRQ 分配状态。
    /proc/ioports 目前系统上面各个装置所配置的 I/O 位址。
    /proc/kcore 这个就是内存的大小啦!好大对吧!但是不要读他啦!
    /proc/loadavg 还记得 top 以及 uptime 吧?没错!上头的三个平均数值就是记录在此!
    /proc/meminfo 使用 free 列出的内存资讯,嘿嘿!在这里也能够查阅到!
    /proc/modules 目前我们的 Linux 已经加载的模块列表,也可以想成是驱动程序啦!
    /proc/mounts 系统已经挂载的数据,就是用 mount 这个命令呼叫出来的数据啦!
    /proc/swaps 到底系统挂加载的内存在哪里?呵呵!使用掉的 partition 就记录在此啦!
    /proc/partitions 使用 fdisk -l 会出现目前所有的 partition 吧?在这个文件当中也有纪录喔!
    /proc/pci 在 PCI 汇流排上面,每个装置的详细情况!可用 lspci 来查阅!
    /proc/uptime 就是用 uptime 的时候,会出现的资讯啦!
    /proc/version 核心的版本,就是用 uname -a 显示的内容啦!
    /proc/bus/* 一些汇流排的装置,还有 U盘 的装置也记录在此喔!

    16.4.3. 查询已打开文件或已执行程序打开之文件

    fuser:借由文件(或文件系统)找出正在使用该文件的程序

    [root@www ~]# fuser [-umv] [-k [i] [-signal]] file/dir
    选项与参数:
    -u  :除了程序的 PID 之外,同时列出该程序的拥有者;
    -m  :后面接的那个档名会主动的上提到该文件系统的最顶层,对 umount 不成功很有效!
    -v  :可以列出每个文件与程序还有命令的完整相关性!
    -k  :找出使用该文件/目录的 PID ,并试图以 SIGKILL 这个讯号给予该 PID;
    -i  :必须与 -k 配合,在删除 PID 之前会先询问使用者意愿!
    -signal:例如 -1 -15 等等,若不加的话,默认是 SIGKILL (-9) 罗!
    
    范例一:找出目前所在目录的使用 PID/所属帐号/权限 为何?
    [root@www ~]# fuser -uv .
                         USER        PID ACCESS COMMAND
    .:                   root      20639 ..c.. (root)bash
    

    ACCESS 的项目代表的意义为:

    • c :此程序在当前的目录下(非次目录);

    • e :可被触发为执行状态;

    • f :是一个被打开的文件;

    • r :代表顶层目录 (root directory);

    • F :该文件被打开了,不过在等待回应中;

    • m :可能为分享的动态函数库;

    lsof :列出被程序所打开的文件文件名

    lsof - list open files

    查出某个程 序打开或者使用的文件与设备

    [root@www ~]# lsof [-aUu] [+d]
    选项与参数:
    -a  :多项数据需要『同时成立』才显示出结果时!
    -U  :仅列出 Unix like 系统的 socket 文件类型;
    -u  :后面接 username,列出该使用者相关程序所开启的文件;
    +d  :后面接目录,亦即找出某个目录底下已经被开启的文件!
    
    范例一:列出目前系统上面所有已经被开启的文件与装置:
    [root@www ~]# lsof
    
    范例二:仅列出关於 root 的所有程序开启的 socket 文件
    [root@www ~]# lsof -u root -a -U
    
    范例三:请列出目前系统上面所有的被启动的周边装置
    [root@www ~]# lsof +d /dev
    
    范例四:秀出属於 root 的 bash 这支程序所开启的文件
    [root@www ~]# lsof -u root | grep bash
    
    # 查看端口占用
    lsof -i:3306
    
    # 查看进程打开了哪些文件
    lsof -p 12
    
    # 查看远程已打开的网络连接
    lsof -i @9.134.205.9
    

    pidof :找出某支正在执行的程序的 PID

    [root@www ~]# pidof [-sx] program_name
    选项与参数:
    -s  :仅列出一个 PID 而不列出所有的 PID
    -x  :同时列出该 program name 可能的 PPID 那个程序的 PID
    
    范例一:列出目前系统上面 init 以及 syslogd 这两个程序的 PID
    [root@www ~]# pidof init syslogd
    1 4286
    # 理论上,应该会有两个 PID 才对。上面的显示也是出现了两个 PID 喔。
    # 分别是 init 及 syslogd 这两支程序的 PID 啦。
    

    通过这个 pidof 指令,并且配合 ps aux 与正则表达式,就可以很轻易的找 到您所想要的程序内容了

    16.5 SELinux 初探

    16.5.1 什么是 SELinux

    SELinux 是“ Security Enhanced Linux ”的缩写,字面上的意义就是安全强 化的 Linux 之意

    当初设计的目标:避免资源的误用

    SELinux 是由美国国家安全局 (NSA) 开发的,当初开发这玩意儿的目的是因为很多企业界 发现, 通常系统出现问题的原因大部分都在于“内部员工的资源误用”所导致的,实际由外部 发动的攻击反而没有这么严重。

    SELinux 是整合到核心的一个模块

    其实 SELinux 是在进行程序、文件等细部权限设置依据的一个核心模块! 由于 启动网络服务的也是程序,因此刚好也能够控制网络服务能否存取系统资源的一道关卡

    传统的文件权限与帐号关系:自主式存取控制, DAC

    系统的帐号主要分为系统管理员 (root) 与一般用户,而这两种 身份能否使用系统上面的文件资源则与 rwx 的权限设置有关。 不过你要注意的是,各种权限 设置对 root 是无效的。因此,当某个程序想要对文件进行存取时, 系统就会根据该程序的拥 有者/群组,并比对文件的权限,若通过权限检查,就可以存取该文件了。

    这种存取文件系统的方式被称为“自主式存取控制 (Discretionary Access Control, DAC)”,基本上,就是依据程序的拥有者与文件资源的 rwx 权限来决定有无存取的能力。 不过这种 DAC 的存取控制有几个困扰,那就是:

    • root 具有最高的权限

    • 使用者可以取得程序来变更文件资源的存取权限

    以政策规则订定特定程序读取特定文件:委任式存取控制, MAC

    DAC 的困扰就是当使用者取得程序后,他可以借由这支程序与自己默认的权限 来处理他自己的文件资源。 万一这个使用者对 Linux 系统不熟,那就很可能会有资源误用的 问题产生。为了避免 DAC 容易发生的问题,因此 SELinux 导入了委任式存取控制 (Mandatory Access Control, MAC) 的方法!

    委任式存取控制 (MAC) 有趣啦!他可以 针对特定的程序与特定的文件资源来进行权限的控 管 ! 也就是说,即使你是 root ,那么在使用不同的程序时,你所能取得的权限并不一定是 root , 而得要看当时该程序的设置而定。如此一来,我们针对控制的“主体”变成了“程序”而不 是使用者喔! 此外,这个主体程序也不能任意使用系统文件资源,因为每个文件资源也有针 对该主体程序设置可取用的权限! 如此一来,控制项目就细的多了!但整个系统程序那么 多、文件那么多,一项一项控制可就没完没了! 所以 SELinux 也提供一些默认的政策 (Policy) ,并在该政策内提供多个规则 (rule) ,让你可以选择是否启用该控制规则!

    左图是没有 SELinux 的 DAC 存取结果,apache 这只 root 所主导的程序,可以在这三个目录 内作任何文件的新建与修改~ 相当麻烦~右边则是加上 SELinux 的 MAC 管理的结果, SELinux 仅会针对 Apache 这个“ process ”放行部份的目录, 其他的非正规目录就不会放行 给 Apache 使用!因此不管你是谁,就是不能穿透 MAC 的框框

    16.5.2 SELinux 的运行模式

    SELinux 是通过 MAC 的方式来控管程序,他控制的主体是程序, 而 目标则是该程序能否读取的“文件资源”!

    • 主体 (Subject): SELinux 主要想要管理的就是程序,因此你可以将“主体”跟本章谈到 的 process 划上等号;

    • 目标 (Object): 主体程序能否存取的“目标资源”一般就是文件系统。因此这个目标项 目可以等文件系统划上等号;

    • 政策 (Policy): 由于程序与文件数量庞大,因此 SELinux 会依据某些服务来制订基本 的存取安全性政策。这些政策内还会有详细的规则 (rule) 来指定不同的服务开放某些 资源的存取与否。在目前的 CentOS 7.x 里面仅有提供三个主要的政策,分别是:

      • targeted:针对网络服务限制较多,针对本机限制较少,是默认的政策;

      • minimum:由 target 修订而来,仅针对选择的程序来保护!

      • mls:完整的 SELinux 限制,限制方面较为严格。建议使用默认的 targeted 政策即 可。

    • 安全性本文 (security context): 我们刚刚谈到了主体、目标与政策面,但是主体能不 能存取目标除了政策指定之外,主体与目标的安全性本文必须一致才能够顺利存取。 这 个安全性本文 (security context) 有点类似文件系统的 rwx 啦!安全性本文的内容与设 置是非常重要的! 如果设置错误,你的某些服务(主体程序)就无法存取文件系统(目 标资源),当然就会一直出现“权限不符”的错误讯息了!

    SELinux 运行的各组件之相关性

    1. 主体程序 必须要通过 SELinux 政策内的规则放行后,就可以与目标资源进行安全性本文的比对

    2. 若比对失败则无法存取目标,若比对成功则可以开始存取目标。问题是,最终能否存取 目标还是与文件系统的 rwx 权限设置有关

    安全性本文 (Security Context)

    安全性本文你就将他想成 SELinux 内必备的 rwx 就是

    [root@study ~]# ls -Z
    -rw-------. root root system_u:object_r:admin_home_t:s0 anaconda-ks.cfg 
    -rw-r--r--. root root system_u:object_r:admin_home_t:s0 initial-setup-ks.cfg 
    -rw-r--r--. root root unconfined_u:object_r:admin_home_t:s0 regular_express.txt
    
    Identify:role:type
    身份识别:角色:类型
    
    • 身份识别 (Identify):

      • unconfined_u:不受限的用户,也就是说,该文件来自于不受限的程序所产生的!一般 来说,我们使用可登陆帐号来取得 bash 之后, 默认的 bash 环境是不受 SELinux 管制 的~因为 bash 并不是什么特别的网络服务!因此,在这个不受 SELinux 所限制的 bash 程序所产生的文件, 其身份识别大多就是 unconfined_u 这个“不受限”用户啰!

      • system_u:系统用户,大部分就是系统自己产生的文件啰!

    • 角色 (Role):

      • object_r:代表的是文件或目录等文件资源,这应该是最常见的啰;

      • system_r:代表的就是程序啦!不过,一般使用者也会被指定成为 system_r 喔!

    • 类型 (Type) (最重要!):

      在默认的 targeted 政策中, Identify 与 Role 字段基本上是不重要的!重要的在于这个类型 (type) 字段。类 型字段在文件与程序的定义不太相同,分别是:

      • type:在文件资源 (Object) 上面称为类型 (Type)

      • domain:在主体程序 (Subject) 则称为领域 (domain)

      domain 需要与 type 搭配,则该程序才能够顺利的读取文件资源啦

    16.5.3 SELinux 三种模式的启动、关闭与观察

    SELinux 依据启动与否,共有三种模式,分别如下:

    • enforcing:强制模式,代表 SELinux 运行中,且已经正确的开始限制 domain/type 了;

    • permissive:宽容模式:代表 SELinux 运行中,不过仅会有警告讯息并不会实际限制 domain/type 的存取。这种模式可以运来作为 SELinux 的 debug 之用;

    • disabled:关闭,SELinux 并没有实际运行。

    # 获取目前的 SELinux 模式
    getenforce
    

    很多发行版都是禁用 SELinux 的,实用性不高

  • 相关阅读:
    [转]tf.summary() 用法
    PASCAL VOC工具包解读
    [ERROR] 安装完Detectron后出现 cython_nms.so: undefined symbol: PyFPE_jbuf
    用Tensorflow做蝴蝶检测
    双系统,重装ubuntu后无法进入windows
    [Error]NodeDef mentions attr 'identical_element_shapes' not in Op<name=TensorArrayV3;
    [转]调试 smallcorgi/Faster-RCNN_TF 的demo过程遇到的问题
    js交互轮播图
    js取俩个数之间的随机数
    原生js实现触摸滚动轮播图
  • 原文地址:https://www.cnblogs.com/huangwenjie/p/16870708.html
Copyright © 2020-2023  润新知