程序管理篇
如何产生一个程序呢?就是执行一个程式或指令,系统只认识二进制文件,当我们启动一个二进制文件的时候会生成程序,而二进制文件里的东西就是程式,程式被某个条件触发生成程序。
程式一般是放置在实体磁碟中,然后透过使用者的执行来触发。触发后会载入到记忆体中成为一个个体,那就是程序。
程序有给予执行者的权限/属性等参数,并包括程式所需要的指令码与资料或档案资料等, 最后再给予一个PID 。系统就是透过这个PID 来判断该process 是否具有权限进行工作的
也就是说,当我们登入并执行bash时,系统已经给我们一个PID了,这个PID就是依据登入者的UID/GID (/etc/passwd)来的
我们知道/bin/bash是一个程式(program),当dmtsai登入后,他取得一个PID号码为2234的程序,这个程序的User/Group都是dmtsai ,而当这个程式进行其他作业时,例如上面提到的touch这个指令时,那么由这个程序衍生出来的其他程序在一般状态下,也会沿用这个程序的相关权限
让我们将程式与程序作个总结:
- 程式(program):通常为binary program ,放置在储存媒体中(如硬碟、光碟、软碟、磁带等), 为实体档案的型态存在;
- 程序(process):程式被触发后,执行者的权限与属性、程式的程式码与所需资料等都会被载入记忆体中, 作业系统并给予这个记忆体内的单元一个识别码(PID),可以说,程序就是一个正在运作中的程式。
关于父进程与子进程
程式彼此之间是有相关性的,连续执行两个bash 后,第二个bash 的父程序就是前一个bash。因为每个程序都有一个PID ,那某个程序的父程序该如何判断?就透过Parent PID (PPID) 来判断即可。
fork and exec:程序呼叫的流程
系统先以fork 的方式复制一个与父程序相同的暂存程序,这个程序与父程序唯一的差别就是PID 不同!但是这个暂存程序还会多一个PPID 的参数,PPID 如前所述,就是父程序的程序识别码,然后暂存程序开始以exec 的方式载入实际要执行的程式,以上述图示来讲,新的程式名称为qqq ,最终子程序的程式码就会变成qqq 了
系统或网路服务:常驻在记忆体的程序
就是会一直运行的程序。
主要大致分成系统本身所需要的服务,例如刚刚提到的crond及atd ,还有rsyslogd等等的。还有一些则是负责网路连线的服务,例如Apache, named, postfix, vsftpd...等等的
工作管理
『进行工作管理的行为中,其实每个工作都是目前bash的子程序,亦即彼此之间是有相关性的。我们无法以job control的方式由tty1的环境去管理tty2的bash !』
在可以出现提示字元让你操作的环境就称为前景(foreground),至于其他工作就可以让你放入背景(background)去暂停或运作。要注意的是,放入背景的工作想要运作时,他必须不能够与使用者互动。举例来说, vim绝对不可能在背景里面执行(running)的!因为你没有输入资料他就不会跑啊!而且放入背景的工作是不可以使用[ctrl]+c来终止
总之,要进行bash 的job control 必须要注意到的限制是:
- 这些工作所触发的程序必须来自于你shell 的子程序(只管理自己的bash);
- 前景:你可以控制与下达指令的这个环境称为前景的工作(foreground);
- 背景:可以自行运作的工作,你无法使用[ctrl]+c 终止他,可使用bg/fg 呼叫该工作;
- 背景中『执行』的程序不能等待terminal/shell 的输入(input)
job control 管理
直接将指令放到后台(背景)运行
我在输入一个指令后,在该指令的最后面加上一个『 & 』代表将该指令丢到背景中, 此时bash 会给予这个指令一个『工作号码(job number)』 ,就是那个[1] 啦!至于后面那个14432 则是该指令所触发的『 PID 』了,这里注意工作号码和pid不是一个东西,该任务如果执行完毕或出问题,提示会跑到前台,所以要将提示信息导入一个文件中存起来,防止出提示信息影响前台工作,另一方面,在后台运行的程序无法用ctrl+c结束。
如此一来,输出的资讯都给他传送到/tmp/log.txt 当中
将『目前』的工作丢到背景中『暂停』:[ctrl]-z
在vim的一般模式下,按下[ctrl]及z这两个按键,萤幕上会出现[1] ,表示这是第一个工作,而那个+代表最近一个被丢进背景的工作,且目前在背景下预设会被取用的那个工作(与fg这个指令有关)!而那个Stopped则代表目前这个工作的状态。在预设的情况下,使用[ctrl]-z丢到背景当中的工作都是『暂停』的状态
观察目前的背景工作状态: jobs
那个+代表预设的取用工作,『目前我有两个工作在背景当中,两个工作都是暂停的,而如果我仅输入fg时,那么那个[2]会被拿到前景当中来处理』
将背景工作拿到前景来处理:fg
我们会发现+出现在第一个工作后!怎么会这样啊?这是因为你刚刚利用fg %1将第一号工作捉到前景后又放回背景,此时最后一个被放入背景的将变成vi那个指令动作,所以当然[1]后面就会出现+了
让工作在背景下的状态变成运作中: bg
这里那jobs;bg %3 ; jobs是三个命令,用;隔开而已
管理背景当中的工作: kill
kill 后面接的数字预设会是PID ,如果想要管理bash 的工作控制,就得要加上%数字了
至少记得kill -15是正常结束进程,kill -9是强制结束进程
离线管理问题
如果你想要让在背景的工作在你登出后还能够继续的执行,那么使用nohup 搭配&
程序观察
- 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 -l 输出讯息中,他说明的是:『bash 的程式属于UID 为0 的使用者,状态为睡眠(sleep), 之所以为睡眠因为他触发了ps (状态为run)之故。此程序的PID 为14836,优先执行顺序为80 , 下达bash 所取得的终端介面为pts/0 ,运作状态为等待(wait) 。』
- 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 的顺序来排序显示,我们还是以14836 那个PID 那行来说明!该行的意义为『 root 执行的bash PID 为14836,占用了0.1% 的记忆体容量百分比,状态为休眠(S),该程序启动的时间为8 月4 号,因此启动太久了, 所以没有列出实际的时间点。且取得的终端机环境为pts/0 。』与ps aux 看到的其实是同一个程序
top 动态观察程序的变化
在预设的情况下,每次更新程序资源的时间为5 秒,不过,可以使用-d 来进行修改。top 主要分为两个画面,上面的画面为整个系统的资源使用状态,基本上总共有六行,显示的内容依序是:
- 第一行(top...):这一行显示的资讯分别为:
- 目前的时间,亦即是00:53:59 那个项目;
- 开机到目前为止所经过的时间,亦即是up 6:07, 那个项目;
- 已经登入系统的使用者人数,亦即是3 users, 项目;
- 系统在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 的结果输出成为档案时, 可以这样做:
观察指定的单一程序:
修改NI(越小越优先):
在你完成上面的动作后,在状态列会出现如下的资讯:
接下来你就会看到如下的显示画面!
想要找出最损耗CPU 资源的那个程序时,大多使用的就是top 这支程式,然后强制以CPU 使用资源来排序(在top 当中按下P 即可)
关于pstree
可以加管道符号缩小范围
killall -signal 指令名称
kill -1 重启
-9 强杀
-15正常中断
grep -v表示去除包含grep的进程,awk '{$2}'表示输出第二个元素就是pid,如果改成1则输出root
killall 更方便的操作
利用『下达指令的名称』来给予讯号
删除某个程序,我们可以使用PID 或者是启动该程序的指令名称, 而如果要删除某个服务呢?呵呵!最简单的方法就是利用killall , 因为他可以将系统当中所有以某个指令名称启动的程序全部删除。
程序优先度调整
我们知道CPU 一秒钟可以运作多达数G 的微指令次数,透过核心的CPU 排程可以让各程序被CPU 所切换运作, 因此每个程序在一秒钟内或多或少都会被CPU 执行部分的指令码。如果程序都是集中在一个队列运作, 而不具有优先顺序之分,也就是像我们去游乐场玩热门游戏需要排队一样,每个人都是照顺序来!你玩过一遍后还想再玩(没有执行完毕),请到后面继续排队等待。情况有点像底下这样:
假设pro1, pro2 是紧急的程序, pro3, pro4 是一般的程序,在这样的环境中
我们可以将程序的优先顺序与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 -n N command 』那个N 指的是『在原本的nice 值底下,再加上的一个值,变成新的nice 值』之意。所以在上面的范例中,原本的nice 为10,使用了nice -n -5 之后,就会变成(10+(-5)),最终结果就是5!并不是直接指定nice 值
已存在程序的nice 重新调整
虽然修改的是bash那个程序,但是该程序所触发的ps指令当中的nice也会继承而为-5!了解了吧!整个nice值是可以在父程序-->子程序之间传递的!另外,除了renice之外,其实那个top同样的也是可以调整nice值的!
系统资源的观察
free 观察内存(记忆体)
我的系统当中有2848MB 左右的实体记忆体,我的swap 有1GB 左右, 那我使用free -m 以MBytes 来显示时,就会出现上面的资讯。Mem 那一行显示的是实体记忆体的量, Swap 则是记忆体置换空间的量。total 是总量, used 是已被使用的量, free 则是剩余可用的量。后面的shared/buffers/cached 则是在已被使用的量当中,用来作为缓冲及快取的量,这些shared/buffers/cached 的用量中,在系统比较忙碌时, 可以被释出而继续利用!因此后面就有一个available (可用的) 数值!。
我们可以发现这部测试机根本没有什么特别的服务,但是竟然有706MB 左右的cache !因为鸟哥在测试过程中还是有读/写/执行很多的档案嘛!这些档案就会被系统暂时快取下来,等待下次运作时可以更快速的取出之意!也就是说,系统是『很有效率的将所有的记忆体用光光』,目的是为了让系统的存取效能加速,一般来说, swap 最好不要被使用,尤其swap 最好不要被使用超过20% 以上, 如果您发现swap 的用量超过20% ,那么,最好还是买实体记忆体来插吧!因为, Swap 的效能跟实体记忆体实在差很多,而系统会使用到swap , 绝对是因为实体记忆体不足了才会这样做的
uname:查阅系统与核心相关资讯
uname 可以列出目前系统的核心版本、 主要硬体平台以及CPU 类型等等的资讯。以上面范例一的状态来说,我的Linux 主机使用的核心名称为Linux,而主机名称为study.centos.vbird,核心的版本为3.10.0-229.el7.x86_64 ,该核心版本建立的日期为2015-3-6,适用的硬体平台为x86_64 以上等级的硬体平台。
uptime:观察系统启动时间与工作负载
显示出目前系统已经开机多久的时间,以及1, 5, 15分钟的平均负载
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);
除了网路上的连线之外,其实Linux系统上面的程序是可以接收不同程序所发送来的资讯,那就是Linux上头的插槽档(socket file)
上表中socket file的输出栏位有:
- Proto :一般就是unix 啦;
- RefCnt:连接到此socket 的程序数量;
- Flags :连线的旗标;
- Type :socket 存取的类型。主要有确认连线的STREAM 与不需确认的DGRAM 两种;
- State :若为CONNECTED 表示多个程序之间已经连线建立。
- Path :连接到此socket 的相关程式的路径!或者是相关资料输出的路径。
侦测系统资源变化
利用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以后才支持)
具有SUID/SGID 权限的指令执行状态
- SUID 权限仅对二进位程式(binary program)有效;
- 执行者对于该程式需要具有x 的可执行权限;
- 本权限仅在执行该程式的过程中有效(run-time);
- 执行者将具有该程式拥有者(owner) 的权限。
整个SUID的权限会生效是由于『具有该权限的程式被触发』,而我们知道一个程式被触发会变成程序,所以啰,执行者可以具有程式拥有者的权限就是在该程式变成程序的那个时候
你或许那时候会觉得很奇怪,为啥执行了passwd后你就具有root的权限呢?不都是一般使用者执行的吗?这是因为你在触发passwd后,会取得一个新的程序与PID,该PID产生时透过SUID来给予该PID特殊的权限设定啦!我们使用dmtsai登入系统且执行passwd后,透过工作控制来理解一下!
如何查询整个系统的SUID/SGID的档案呢
find / -perm /6000
fuser:藉由档案(或档案系统)找出正在使用该档案的程序
想要知道我的程序到底在这次启动过程中开启了多少档案,可以利用fuser 来观察啦!举例来说,你如果卸载时发现系统通知:『 device is busy 』,那表示这个档案系统正在忙碌中, 表示有某支程序有利用到该档案系统
- c :此程序在当前的目录下(非次目录);
- e :可被触发为执行状态;
- f :是一个被开启的档案;
- r :代表顶层目录(root directory);
- F :该档案被开启了,不过在等待回应中;
- m :可能为分享的动态函式库;
仅针对单一档案
如何查出某个程序开启或者使用的档案与装置呢?呼呼!那就是使用lsof
找出某支正在执行的程式的PID