1 进程
在 Linux 中运行一个命令时,系统会将相关的权限、属性、程序码与数据等均加载内存, 并给予这个单元一个程序识别码(PID),最终该命令可以进行的任务则与这个 PID 的权限有关。
1.1 进程和程序
1 程序和进程区别
程序一般是放置在实体磁碟中,然后透过使用者的运行来触发。触发后会加载到内存中成为一个个体,那就是程序。
为了操作系统可管理这个程序,因此程序有给予运行者的权限/属性等参数,并包括程序所需要的命令码与数据或文件数据等, 最后再给予一个 PID 。系统就是透过这个 PID 来判断该 process 是否具有权限进行工作的!
==程序== (program):通常为二进制,放置在储存媒体中 (如硬盘、光盘、软盘、磁带等), 为实体文件的型态存在;
==进程== (process):程序被触发后,运行者的权限与属性、程序的程序码与所需数据等都会被加载内存中, 操作系统并给予这个内存内的单元一个识别码 (PID),可以说,进程就是一个正在运行中的程序。
2 父子进程
当我们登陆系统后,会取得一个 bash 的 shell ,然后,我们用这个 bash 提供的介面去运行另一个命令,例如 /usr/bin/passwd 或者是 touch 等等,那些另外运行的命令也会被触发成为 PID ,那个后来运行命令才产生的 PID 就是子程序了,而在我们原本的 bash 环境下,就称为父程序。
其实,我们登陆 bash 之后, 就是取得一个名为 bash 的 PID 了,而在这个环境底下所运行的其他命令, 就几乎都是所谓的子程序了。
fork and exec
子程序与父程序之间的关系还挺复杂的,最大的复杂点在於程序互相之间的呼叫。在 Linux 的程序呼叫通常称为 fork-and-exec 的流程。
- 系统先以 fork 的方式复制一个与父程序相同的缓存程序,这个程序与父程序唯一的差别就是 PID 不同! 但是这个缓存程序还会多一个 PPID 的参数,PPID 如前所述,就是父程序的程序识别码啦!
- 缓存程序开始以 exec的方式加载实际要运行的程序,以上述图示来讲,新的程序名称为 qqq ,最终子程序的程序码就会变成 qqq 了! 这样了解乎!
系统或网络服务:常驻在内存的程序
常驻在内存当中的程序通常都是负责一些系统所提供的功能以服务使用者各项任务,因此这些常驻程序就会被我们称为:服务 (daemon)。
一些负责网络连线的服务,例如 Apache, named, postfix, vsftpd等等。这些网络服务比较有趣的地方,在於这些程序被运行后,他会启动一个可以负责网络监听的端口 (port) ,以提供外部用户端 (client) 的连线要求。
1.2 Linux多用户、多任务环境
- 多用户环境:在 Linux 系统上面具有多种不同的帐号, 每种帐号都有都有其特殊的权限,只有一个人具有至高无上的权力,那就是 root (系统管理员)。除了 root之外,其他人都必须要受一些限制的!每个人登陆后取得的 shell 的 PID 不同。
- 多任务行为: Linux 可以让 CPU 在各个工作间进行切换, 也就是说,其实每个工作都仅占去 CPU 的几个命令次数,所以 CPU 每秒就能够在各个程序之间进行切换。 目前 Linux 使用的多工切换行为是非常棒的一个机制,几乎可以将 PC 的性能整个压榨出来! 由於效能非常好,因此当多人同时登陆系统时,其实会感受到整部主机好像就为了你存在一般! 这就是多人多工的环境啦!
2. 工作管理 (job control)
这个工作管理 (job control) 是用在 bash 环境下的,也就是说:当我们登陆系统取得 bash shell 之后,在单一终端机介面下同时进行多个工作的行为管理 。举例来说,我们在登陆 bash 后, 想要一边复制文件、一边进行数据搜寻、一边进行编译,还可以一边进行 vi 程序撰写! 当然我们可以重复登陆那六个文字介面的终端机环境中,不过,能不能在一个 bash 内达成? 当然可以啊!就是使用 job control。
2.1 什么是工作管理
==注意==:进行工作管理的行为中, 其实每个工作都是目前 bash 的子程序,亦即彼此之间是有相关性的。 我们无法以 job control 的方式由 tty1 的环境去管理 tty2 的 bash。
要进行 bash 的 job control 必须要注意到的限制是:
- 这些工作所触发的程序必须来自於你 shell 的子程序(只管理自己的 bash);
- 前台:你可以控制与下达命令的这个环境称为前台的工作 (foreground);
- 后台:可以自行运行的工作,你无法使用 [ctrl]+c 终止他,可使用 bg/fg 呼叫该工作;
- 后台中运行的程序不能等待 terminal/shell 的输入(input)。
2.2 job control 的管理
2.2.1 直接将命令在后台运行的“&”:
举个简单的例子,我们要将 ~/springboot-beatlsql打包为~/springboot-beatlsql.tar.gz 且不想要等待,那么可以这样做:
[root@www ~]# tar -zcf springboot-beatlsql.tar.gz springboot-beatlsql &
[1] 8400 <== [job number] PID
[root@www ~]# tar: Removing leading `/' from member names
# 在中括号内的号码为工作号码 (job number),该号码与 bash 的控制有关。
# 后续的 8400 则是这个工作在系统中的 PID。至于后续出现的数据是 tar 运行的数据流,
# 由于我们没有加上数据流重导向,所以会影响画面!不过不会影响前景的操作喔!
好处:不怕被 [ctrl]+c 中断!
==改进==:
在后台当中运行的命令,如果有 stdout 及 stderr 时,他的数据依旧是输出到萤幕上面的。由於是后台工作的 tar , 此时你怎么按下 [ctrl]+c 也无法停止萤幕被搞的花花绿绿的!所以,最佳的状况就是利用数据流重导向, 将输出数据传送至某个文件中。举例来说,我可以这样做:
[root@www ~]$ tar -zcvf springboot-beatlsql.tar.gz springboot-beatlsql > log.txt 2>&1 &
上面将打包的输出信息(包括标准输出和错误输出)都放入log文件中,不会影响前台工作。
2.2.2 将目前的工作丢到后台中暂停:[ctrl]-z
想个情况:如果我正在使用 vi ,却发现我有个文件不知道放在哪里,需要到 bash 环境下进行搜寻,此时是否要结束 vi 呢?呵呵!当然不需要!只要暂时将 vi 给他丢到后台当中等待即可。 例如以下的案例:
[root@www ~]# vi ~/.bashrc
# 在 vi 的一般模式下,按下 [ctrl]-z 这两个按键
[1]+ Stopped vim ~/.bashrc
[root@www ~]# <==顺利取得了前景的操控权!
[root@www ~]# find / -print
....(输出省略)....
# 此时萤幕会非常的忙碌!因为萤幕上会显示所有的档名。请按下 [ctrl]-z 暂停
[2]+ Stopped find / -print
在 vi 的一般模式下,按下 [ctrl] 及 z 这两个按键,萤幕上会出现 [1] ,表示这是第一个工作, 而那个 + 代表最近一个被丢进背景的工作,且目前在背景下默认会被取用的那个工作 (与 fg 这个命令有关 )!而那个 Stopped 则代表目前这个工作的状态。在默认的情况下,使用 [ctrl]-z 丢到背景当中的工作都是暂停的状态!
2.2.3 查看目前的后台状态: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
2.2.4 将后台工作拿到前台处理: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
2.2.5 让工作在后台下的状态变成运行中:bg(暂时没这需求)
2.2.6 管理背景当中的工作: kill
上面可以使用 fg 将后台工作拿到前台来, 那么,如果想要将该工作直接移除呢?或者是将该工作重新启动呢?这个时候就得需要给予该工作一个讯号 (signal) ,此时, kill 这个命令就派上用场啦!
[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 来查阅!
kill 后面接的数字默认会是 PID ,如果想要管理 bash 的工作控制,就得要加上 %数字 了, 这点也得特别留意才行!
2.3 离线管理问题:nohup
要注意的是,我们在工作管理当中提到的后台指的是在终端机模式下可以避免 [crtl]-c 中断的一个情境, 并不是放到系统的后台!所以,工作管理的背景依旧与终端机有关啦! 在这样的情况下,如果你是以远程连线方式连接到你的 Linux 主机,并且将工作以 & 的方式放到后台去, 请问,在工作尚未结束的情况下你离线了,该工作还会继续进行吗?答案是『否』!不会继续进行,而是会被中断掉。
- 方法一: at 来处理!因为 at 是将工作放置到系统后台, 而与终端机无关。
- 方法二:使用nohup!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
3 进程管理
3.1 进程查看
利用静态的 ps 或者是动态的 top,还能以 pstree 来查阅程序树之间的关系。
3.1.1 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 』!
3.1.2 仅观察自己的“ bash” 相关程序: ps -l
[root@www ~]$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 503 2449 2448 0 80 0 - 27592 do_wai pts/3 00:00:00 bash
4 S 503 2641 2640 0 80 0 - 27592 do_wai pts/3 00:00:00 bash
0 R 503 2661 2641 0 80 0 - 27437 - pts/3 00:00:00 ps
3.1.3 查看系统所有程序: ps aux
3.1.4 动态查看进程: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 软件的按键。
3.1.5 pstree
[root@www ~]# pstree [-A|U] [-up]
选项与参数:
-A :各程序树之间的连接以 ASCII 字节来连接;
-U :各程序树之间的连接以万国码的字节来连接。在某些终端介面下可能会有错误;
-p :并同时列出每个 process 的 PID;
-u :并同时列出每个 process 的所属帐号名称。
3.2 进程管理
程序之间是可以互相控制的!举例来说,你可以关闭、重新启动服务器软件,服务器软件本身是个程序,你既然可以让她关闭或启动,当然就是可以控制该程序啦!那么程序是如何互相管理的呢?其实是透过给予该程序一个讯号 (signal) 去告知该程序你想要让她作什么!因此这个讯号就很重要!
那么到底有多少 signal 呢? 你可以使用 kill -l (小写的 L ) 或者是 man 7 signal 都可以查询到!主要的讯号代号与名称对应及内容是:
代号 | 名称 | 内容 |
---|---|---|
1 | SIGHUP | 启动被终止的程序,可让该 PID重新读取自己的配置档,类似重新启动 |
2 | SIGINT | 相当于用键盘输入 [ctrl]-c 来中断一个程序的进行 |
9 | SIGKILL | 代表强制中断一个程序的进 |
15 | SIGTERM | 以正常的结束程序来终止该程序 |
17 | SIGCHLD | 相当于用键盘输入 [ctrl]-z 来暂停一个程序的进行 |
注意:
1. 必须记住1,9,15;
1. SIGKILL代表强制中断一个程序的进行,如果该程序进行到一半, 那么尚未完成的部分可能会有『半产品』产生,类似 vim会有 .filename.swp 保留下来;
1. SIGCHLD 以正常的结束程序来终止该程序。由於是正常的终止, 所以后续的动作会将他完成。不过,如果该程序已经发生问题,就是无法使用正常的方法终止时, 输入这个 signal 也是没有用的。
3.2.1 kill -signal PID(使用的多)
3.2.2 killall -signal 命令名称
例如
[root@www ~]# killall svnserve
[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 喔! ^_^
3.3 进程执行的顺序
3.3.1 Priority 与 Nice 值
Linux 给予程序一个所谓的优先运行序 (priority, PRI), 这个 PRI 值越低代表越优先的意思。不过这个 PRI 值是由核心动态调整的, 使用者无法直接调整 PRI 值的。先来瞧瞧 PRI 曾在哪里出现?
[root@www ~]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 18625 18623 2 75 0 - 1514 wait pts/1 00:00:00 bash
4 R 0 18653 18625 0 77 0 - 1102 - pts/1 00:00:00 ps
由于 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 命令。
3.3.2 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 关闭
3.3.3 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
3.4 系统资源的查看
3.4.1 free :观察内存使用情况
[root@www ~]# free [-b|-k|-m|-g] [-t]
选项与参数:
-b :直接输入 free 时,显示的单位是 Kbytes,我们可以使用 b(bytes), m(Mbytes)
k(Kbytes), 及 g(Gbytes) 来显示单位喔!
-t :在输出的最终结果,显示实体内存与 swap 的总量。
范例一:显示目前系统的内存容量
[root@www ~]# free -m
total used free shared buffers cached
Mem: 725 666 59 0 132 287
-/+ buffers/cache: 245 479
Swap: 996 0 996
仔细看看,我的系统当中有 725MB 左右的实体内存,我的 swap 有 1GB 左右, 那我使用 free -m 以 MBytes 来显示时,就会出现上面的资讯。
Mem 那一行显示的是实体内存的量, Swap 则是虚拟内存的量。 total 是总量, used 是已被使用的量, free 则是剩余可用的量。 后面的 shared/buffers/cached 则是在已被使用的量当中,用来作为缓冲及缓存的量。
仔细的看到范例一的输出喔,我们的 Linux 测试用主机是很平凡的,根本没有什么工作, 但是,我的实体内存是几乎被用光光的情况呢!不过,至少有 132MB 用在缓冲记忆 (buffers) 工作, 287MB 则用在缓存 (cached) 工作,也就是说,系统是『很有效率的将所有的内存用光光』, 目的是为了让系统的存取效能加速啦!
很多人都会问到这个问题:“我的系统明明很轻松,为何内存会被用光光?” 被用光是正常的!而需要注意的反而是 swap 的量。一般来说, swap 最好不要被使用,尤其 swap 最好不要被使用超过 20% 以上, 如果您发现 swap 的用量超过 20% ,那么,最好还是买实体内存来插吧! 因为, Swap 的效能跟实体内存实在差很多,而系统会使用到 swap , 绝对是因为实体内存不足了才会这样做的!
Linux 系统为了要加速系统效能,所以会将最常使用到的或者是最近使用到的文件数据缓存 (cache) 下来, 这样未来系统要使用该文件时,就直接由内存中搜寻取出,而不需要重新读取硬盘,速度上面当然就加快了! 因此,实体内存被用光是正常的!
3.4.2 uname:查阅系统与核心相关信息
[root@www ~]# uname [-asrmpi]
选项与参数:
-a :所有系统相关的资讯,包括底下的数据都会被列出来;
-s :系统核心名称
-r :核心的版本
-m :本系统的硬件名称,例如 i686 或 x86_64 等;
-p :CPU 的类型,与 -m 类似,只是显示的是 CPU 的类型!
-i :硬件的平台 (ix86)
范例一:输出系统的基本资讯
[root@www ~]# uname -a
Linux www.vbird.tsai 2.6.18-92.el5 #1 SMP Tue Jun 10 18:49:47 EDT 2008 i686
i686 i386 GNU/Linux
uname 可以列出目前系统的核心版本、 主要硬件平台以及 CPU 类型等等的信息。以上面范例一的状态来说,我的 Linux 主机使用的核心名称为 Linux,而主机名称为 www.vbird.tsai,核心的版本为 2.6.18-92.el5 ,该核心版本创建的日期为 2008/6/10,适用的硬件平台为 i386 以上等级的硬件平台。
3.4.3 uptime:查看系统启动时间与工作负载
这个命令很单纯呢!就是显示出目前系统已经启动多久的时间,以及 1, 5, 15 分钟的平均负载就是了。还记得 top 吧?没错啦!这个 uptime 可以显示出 top 画面的最上面一行!
[root@www ~]# uptime
15:39:13 up 8 days, 14:52, 1 user, load average: 0.00, 0.00, 0.00
# top 这个命令已经谈过相关资讯,不再聊!
3.4.4 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
....(中间省略)....
范例二:找出目前系统上已在监听的网络连线及其 PID
[root@www ~]# netstat -ltnp
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
在使用netstat不知道参数时,可以使用口诀:查看所有监听的(l),tcp协议的(t),显示端口的(n),显示PID的(p)
3.4.5 dmesg :分析核心产生的信息
系统在启动的时候,内核会去检测系统的硬件,你的某些硬件到底有没有被捉到,那就与这个时候的侦测有关。 但是这些侦测的过程要不是没有显示在屏幕上,就是很飞快的在萤幕上一闪而逝!能不能把核心侦测的信息捉出来瞧瞧? 可以的,那就使用 dmesg!
所有内核检测的信息,不管是启动时候还是系统运行过程中,反正只要是内核产生的信息,都会被记录到内存中的某个保护区段。 dmesg 这个命令就能够将该区段的信息读出来的!因为信息实在太多了,所以运行时可以加入这个管线命令『 | more 』来使画面暂停!
范例一:输出所有的核心启动时的资讯
[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
....(底下省略)....
4 特殊文件与程序
4.1 具有 SUID/SGID 权限的命令运行状态
SUID 的权限其实与程序的相关性非常的大!为什么呢?先来看看 SUID 的程序是如何被一般使用者运行,且具有什么特色呢?
- SUID 权限仅对二进位程序(binary program)有效;
- 运行者对於该程序需要具有 x 的可运行权限;
- 本权限仅在运行该程序的过程中有效 (run-time);
- 运行者将具有该程序拥有者 (owner) 的权限。
所以说,整个 SUID 的权限会生效是由于『具有该权限的程序被触发』,而我们知道一个程序被触发会变成程序, 所以,运行者可以具有程序拥有者的权限就是在该程序变成程序的那个时候。前面还没谈到程序的概念, 所以你或许那时候会觉得很奇怪,为啥运行了 passwd 后你就具有 root 的权限呢?不都是一般使用者运行的吗? 这是因为你在触发 passwd 后,会取得一个新的程序与 PID,该 PID 产生时透过 SUID 来给予该 PID 特殊的权限配置啦! 我们使用 dmtsai 登陆系统且运行 passwd 后,透过工作控制来理解一下!
[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
....(底下省略)....
从上表的结果我们可以发现,底线的部分是属於 dmtsai 这个一般帐号的权限,特殊字体的则是 root 的权限! 但你看到了, passwd 确实是由 bash 衍生出来的!不过就是权限不一样!透过这样的解析, 你也会比较清楚为何不同程序所产生的权限不同了吧!这是由於『SUID 程序运行过程中产生的程序』的关系啦!
那么既然 SUID/SGID 的权限是比较可怕的,您该如何查询整个系统的 SUID/SGID 的文件呢? 应该是还不会忘记吧?使用 find 即可啊!
find / -perm +6000
4.2 /proc/* :内存数据存放位置
其实,我们之前提到的所谓的程序都是在内存当中嘛!而内存当中的数据又都是写入到 /proc/* 这个目录下的,所以,我们当然可以直接观察 /proc 这个目录当中的文件啊! 如果你观察过 /proc 这个目录的话,应该会发现他有点像这样:
[root@www ~]# ll /proc
dr-xr-xr-x 5 root root 0 Mar 11 08:46 1
dr-xr-xr-x 5 root root 0 Mar 11 00:46 10
dr-xr-xr-x 5 root root 0 Mar 11 00:46 11
....(中间省略)....
-r--r--r-- 1 root root 0 Mar 20 12:11 uptime
-r--r--r-- 1 root root 0 Mar 20 12:11 version
-r--r--r-- 1 root root 0 Mar 20 12:11 vmstat
-r--r--r-- 1 root root 0 Mar 20 12:11 zoneinfo
基本上,目前主机上面的各个程序的 PID 都是以目录的型态存在于 /proc 当中。 举例来说,我们启动所运行的第一支程序 init 他的 PID 是 1 , 这个 PID 的所有相关资讯都写入在 /proc/1/* 当中!若我们直接观察 PID 为 1 的数据好了,他有点像这样:
[root@www ~]# ll /proc/1
dr-xr-xr-x 2 root root 0 Mar 12 11:04 attr
-r-------- 1 root root 0 Mar 17 14:32 auxv
-r--r--r-- 1 root root 0 Mar 17 14:32 cmdline <==就是命令串
-rw-r--r-- 1 root root 0 Mar 17 14:32 coredump_filter
-r--r--r-- 1 root root 0 Mar 17 14:32 cpuset
lrwxrwxrwx 1 root root 0 Mar 17 14:32 cwd -> /
-r-------- 1 root root 0 Mar 17 14:32 environ <==一些环境变量
lrwxrwxrwx 1 root root 0 Mar 17 14:32 exe -> /sbin/init <==实际运行的命令
....(以下省略)....
里面的数据还挺多的,不过,比较有趣的其实是两个文件,分别是:
- cmdline:这个程序被启动的命令串;
- environ:这个程序的环境变量内容。
相关的文件与对应的内容是这样的:
档名 | 文件内容 |
---|---|
/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 | 到底系统挂加载的内存在哪里?呵呵!使用的分区 就记录在此啦! |
/proc/partitions | 使用 fdisk -l 会出现目前所有的分区 吧?在这个文件当中也有纪录 |
/proc/pci | 在 PCI 总线上面,每个设备的详细情况!可用 lspci 来查阅! |
/proc/uptime | 就是用 uptime 的时候,会出现的资讯啦! |
/proc/version | 核心的版本,就是用 uname -a 显示的内容啦! |
/proc/bus/* | 一些总线的设备,还有 U盘 设备也记录在此喔! |