1、进程
在 Linux 系统当中:“触发任何一个事件时,系统都会将他定义成为一个程序,并且给予这个程序一个 ID ,称为 PID,同时依据启发这个程序的使用者与相关属性关系,给予这个 PID 一组有效的权限设置。
1.1 进程与程序
执行一个程序或命令就可以触发一个事件从而获取一个PID;
程序与程序作个总结:
- 程序 (program):通常为 binary program ,放置在储存媒体中 (如硬盘、光盘、软盘、磁带等), 为实体文件的型态存在;
- 进程 (process):程序被触发后,执行者的权限与属性、程序的程序码与所需数据等都会被载入内存中, 操作系统并给予这个内存内的单元一个识别码 (PID),可以说,程序就是一个正在运行中的程序。
子进程与父进程:
范例一:请在目前的 bash 环境下,再触发一次 bash ,并以“ ps -l ”这个指令观察程序相关的输出信息。答:直接执行 bash ,会进入到子程序的环境中,然后输入 ps -l 后,出现:
[root@localhost ~]# bash
[root@localhost ~]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 10366 10124 0 80 0 - 48520 do_wai pts/1 00:00:00 su
4 S 0 10370 10366 0 80 0 - 29082 do_wai pts/1 00:00:00 bash
4 S 0 10699 10370 0 80 0 - 29143 do_wai pts/1 00:00:00 bash
0 R 0 10733 10699 0 80 0 - 38331 - pts/1 00:00:00 ps
fork and exec:程序调用的流程
Linux 的程序调用通常称为 fork-and-exec 的流程;
程序都会借由父程序以复制 (fork) 的方式产生一个一模一样的子程序, 然后被复制出来的子程序再以 exec 的方式来执行实际要进行的程序,最终就成为一个子程序的存在。 整个流程有点像下面这张图:
(1)系统先以 fork 的方式复制一个与父程序相同的暂存程序,这个程序与父程序唯一的差别就是 PID 不同! 但是这个暂存程序还会多一个 PPID 的参数,PPID 如前所述,就是父程序的程序识别码啦!然后
(2)暂存程序开始以 exec 的方式载入实际要执行的程序,以上述图示来讲,新的程序名称为 qqq ,最终子程序的程序码就会变成 qqq 了
1.2 Linux 的多用户多任务环境
在单一的 bash 接口下,可以进行多个工作,举例来说,我可以这样做:
[root@study ~]# cp file1 file2 &
在这一串指令中,重点在那个 & 的功能,他表示将 file1 这个文件复制为 file2 ,且放置于背景中执行, 也就是说执行这一个命令之后,在这一个终端接口仍然可以做其他的工作!而当这一个指令 (cp file1 file2) 执行完毕之后,系统将会在你的终端接口显示完成的消息!
2 工作管理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 的管理
实际进行 job 控制的指令如下:
2.2.1 直接将指令丢到背景中“执行”的 &;
在指令的最后面加上一个“ & ”代表将该指令丢到后台中执行;
[root@study ~]# tar -zpcf /tmp/etc.tar.gz /etc &
[1] 14432 <== [job number] PID
[root@study ~]# tar: Removing leading `/' from member names
# 在中括号内的号码为工作号码 (job number),该号码与 bash 的控制有关。
# 后续的 14432 则是这个工作在系统中的 PID。至于后续出现的数据是 tar 执行的数据流,
# 由于我们没有加上数据流重导向,所以会影响画面!不过不会影响前台的操作!
后台工作完成后会显示:
[1]+ Done tar -zpcf /tmp/etc.tar.gz /etc
将输出数据重定向到某个文件中:
[root@study ~]# tar -zpcvf /tmp/etc.tar.gz /etc > /tmp/log.txt 2>&1 &
[1] 14547
[root@study ~]#
2.2.2 [ctrl]-z:将【目前】的任务丢到后台【暂停】
若正在使用 vim ,发现有个文件不知放在哪里,需要到 bash 环境下进行搜寻,此时可以选择不结束 vim ,只要暂时将 vim 给他丢到后台当中等待即可。
[root@localhost ~]# vim ~/.bashrc
# 在 vim 的一般模式下,按下 [ctrl]-z 这两个按键
[1]+ 已停止 vim ~/.bashrc
[root@localhost ~]# <==顺利取得了前景的操控权!
[root@localhost ~]# find / -print
....(输出省略)....
# 此时屏幕会非常的忙碌!因为屏幕上会显示所有的文件名。请按下 [ctrl]-z 暂停
[2]+ 已停止 find / -print
vim 的一般模式下,按下 [ctrl] 及 z 这两个按键,屏幕上会出现 [1] ,表示这是第一个工作, 而那个 + 代表最近一个被丢进后台的工作,且是目前后台默认会被使用的那个工作 (与 fg 这个指令有关 )!而那个 Stopped 则代表目前这个工作的状态。在默认的情况下,使用 [ctrl]-z 丢到背景当中的工作都是“暂停”的状态!
2.2.3 jobs:查看目前的后台任务状态
[root@localhost ~]# jobs [-lrs]
选项与参数:
-l :除了列出 job number 与指令串之外,同时列出 PID 的号码;
-r :仅列出正在背景 run 的工作;
-s :仅列出正在背景当中暂停 (stop) 的工作。
范例一:观察目前的 bash 当中,所有的工作,与对应的 PID
[root@localhost ~]# jobs -l
[1]- 12315 停止 vim ~/.bashrc
[2]+ 12349 停止 find / -print
+ 代表默认的取用工作。 所以说:“目前我有两个工作在后台当中,两个工作都是暂停的, 而如果我仅输入 fg 时,那么那个 [2] 会被拿到前景当中来处理”!
+ 代表最近被放到后台的任务号码, - 代表最近的前一个(首先)被放置到后台中的任务号码。 而超过最后第三个以后的工作,就不会有 +/- 符号存在了!
2.2.4 fg:将后台工作拿到前台来处理
[root@localhost ~]# fg %jobnumber
选项与参数:
%jobnumber :jobnumber 为工作号码(数字)。注意,那个 % 是可有可无的!
范例一:先以 jobs 观察工作,再将工作取出:
[root@localhost ~]# jobs -l
[1]- 12315 停止 vim ~/.bashrc
[2]+ 12349 停止 find / -print
[root@localhost ~]# fg <==默认取出那个 + 的工作,亦即 [2]。立即按下[ctrl]-z
[root@localhost ~]# fg %1 <==直接规定取出的那个工作号码!再按下[ctrl]-z
vim ~/.bashrc
[1]+ 已停止 vim ~/.bashrc
[root@localhost ~]# jobs
[1]+ 已停止 vim ~/.bashrc
[2]- 已停止 find / -print
2.2.5 bg:让任务在后台下的状态变成运行中
#范例一:一执行 find / -perm /7000 > /tmp/text.txt 后,立刻丢到背景去暂停!
[root@localhost ~]# find / -perm /7000 > /tmp/text.txt
^Z # 此时,请立刻按下 [ctrl]-z 暂停!
[3]+ 已停止 find / -perm /7000 > /tmp/text.txt
#范例二:让该工作在背景下进行,并且观察他!!
[root@localhost ~]# jobs;bg %3;jobs
[1]- 已停止 vim ~/.bashrc
[2] 已停止 find / -print
[3]+ 已停止 find / -perm /7000 > /tmp/text.txt
[3]+ find / -perm /7000 > /tmp/text.txt &
[1]+ 已停止 vim ~/.bashrc
[2] 已停止 find / -print
[3]- 运行中 find / -perm /7000 > /tmp/text.txt &
2.2.6 kill:管理后台当中的工作
[root@localhost ~]# kill -signal %jobnumber
[root@localhost ~]# kill -l
选项与参数:
-l :这个是 L 的小写,列出目前 kill 能够使用的讯号 (signal) 有哪些?
signal :代表给予后面接的那个工作什么样的指示啰!用 man 7 signal 可知:
-1 :重新读取一次参数的配置文件 (类似 reload);
-2 :代表与由键盘输入 [ctrl]-c 同样的动作;
-9 :立刻强制删除一个工作;
-15:以正常的程序方式终止一项工作。与 -9 是不一样的。
//范例一:找出目前的 bash 环境下的背景工作,并将该工作“强制删除”。
[root@localhost ~]# jobs
[1]+ 已停止 vim ~/.bashrc
[2] 已停止 find / -print
[root@localhost ~]# kill -9 %2; jobs
[1]+ 已停止 vim ~/.bashrc
[2] 已杀死 find / -print
# 再过几秒你再下达 jobs 一次,就会发现 2 号工作不见了!因为被移除了!
//范例二:找出目前的 bash 环境下的背景工作,并将该工作“正常终止”掉。
[root@localhost ~]# kill -SIGTERM %1
[1]+ 已停止 vim ~/.bashrc
# -SIGTERM 与 -15 是一样的!您可以使用 kill -l 来查阅!
# 不过在这个案例中, vim 的工作无法被结束喔!因为他无法通过 kill 正常终止的意思!
2.3 脱机(离线)管理问题nohup
“后台”指的是在终端机模式下可以避免 [crtl]-c 中断的一个情境, 可以说那个是 bash 的后台,并不是放到系统的背景去;
nohup 可以让你在离线或登出系统后,还能够让工作继续进行
[root@study ~]# nohup [指令与参数] <==在终端机前景中工作
[root@study ~]# nohup [指令与参数] & <==在终端机背景中工作
# 1\. 先编辑一支会“睡着 500 秒”的程序:
[root@study ~]# vim sleep500.sh
#!/bin/bash
/bin/sleep 500s
/bin/echo "I have slept 500 seconds."
# 2\. 丢到后台中去执行,并且立刻登出系统:
[root@study ~]# chmod a+x sleep500.sh #事先不知道sleep500.sh权限,只是想给每个人增加可执行权限 chmod a+x sleep500.sh
[root@study ~]# nohup ./sleep500.sh &
[2] 14812
[root@study ~]# nohup: ignoring input and appending output to `nohup.out' <==会告知这个讯息!
[root@study ~]# exit
- 如果你再次登陆的话,再使用 pstree 去查阅你的程序,会发现 sleep500.sh 还在执行中
- 如果你想要让在背景的工作在你登出后还能够继续的执行,那么使用 nohup 搭配 & 是不错的运行情境
3 进程管理
3.1 ps/top/pstree查看进程
3.1.1 ps
[root@study ~]# ps aux <==观察系统所有的进程
[root@study ~]# ps -lA <==也是能够观察所有系统的进程
[root@study ~]# ps axjf <==连同部分进程树状态
#选项与参数:
-A :所有的进程均显示出来,与 -e 具有同样的效果;
-a :不显示与终端有关的所有进程;
-u :有效使用者 (effective user) 相关的进程 ;
x :通常与 a 这个参数一起使用,可列出较完整信息。
#输出格式规划:
l :较长、较详细的将该 PID 的的信息列出;
j :任务的格式 (jobs format)
-f :做一个更为完整的输出。
重点记住查阅自己 bash 进程的“ ps -l ”和查阅所有系统运行的进程命令“ ps aux ”
#范例一:将目前属于您自己这次登陆的 PID 与相关信息列示出来(只与自己的 bash 有关)
[root@localhost ~]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 10366 10124 0 80 0 - 48520 do_wai pts/1 00:00:00 su
4 S 0 10370 10366 0 80 0 - 29082 do_wai pts/1 00:00:00 bash
4 S 0 10699 10370 0 80 0 - 29163 do_wai pts/1 00:00:00 bash
0 R 0 25778 10699 0 80 0 - 38331 - 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 的缩写,造成此程序的触发程序之指令为何。
3.1.2 ps aux:观察系统所有进程
#范例二:列出目前所有的正在内存当中的进程:
[mcb@localhost ~]$ ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.5 194092 5164 ? Ss 7月03 0:07 /usr/lib/systemd/systemd --switched-root --system --deseria
root 2 0.0 0.0 0 0 ? S 7月03 0:00 [kthreadd]
root 4 0.0 0.0 0 0 ? S< 7月03 0:00 [kworker/0:0H]
...(中间省略)...
mcb 2091 0.0 0.5 465100 5724 ? Sl 7月03 0:00 /usr/libexec/ibus-x11 --kill-daemon
mcb 2094 0.0 0.1 376180 1500 ? Sl 7月03 0:00 /usr/libexec/ibus-portal
mcb 2103 0.0 0.1 364920 1080 ? Sl 7月03 0:00 /usr/libexec/xdg-permission-store
...(中间省略)...
mcb 27721 0.0 0.1 155448 1864 pts/0 R+ 09:46 0:00 ps aux
- %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:该程序的实际指令为何?
范例三:找出与 cron 与 rsyslog 这两个服务有关的 PID 号码?
[root@localhost ~]# ps aux | egrep -n 'cron|rsyslog'
99:root 1117 0.0 0.1 220656 1984 ? Ssl 7月03 0:02 /usr/sbin/rsyslogd -n
103:root 1143 0.0 0.1 126420 1132 ? Ss 7月03 0:01 /usr/sbin/crond -n
203:root 28675 0.0 0.0 123360 760 ? Ss 10:01 0:00 /usr/sbin/anacron -s
207:root 28885 0.0 0.0 112828 984 pts/0 R+ 10:04 0:00 grep -E --color=auto -n cron|rsyslog
3.1.3 top:动态查看进程的变化
top可以持续监测进程运行状态,而ps则是选取一个时间点的进程状态
[root@study ~]# 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@localhost ~]# top -d 2
top - 10:19:22 up 16:19, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 205 total, 1 running, 204 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 995676 total, 86688 free, 711704 used, 197284 buff/cache
KiB Swap: 2097148 total, 2024188 free, 72960 used. 106128 avail Mem
<==如果加入 k 或 r 时,就会有相关的字样出现在这里
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
291 root 20 0 0 0 0 S 0.5 0.0 0:15.70 xfsaild/sda3
29757 root 20 0 162100 2368 1600 R 0.5 0.2 0:00.13 top
1 root 20 0 194092 5212 2704 S 0.0 0.5 0:07.82 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.03 kthreadd
4 root 0 -20 0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H
6 root 20 0 0 0 0 S 0.0 0.0 0:00.77 ksoftirqd/0
如果你想要使用内存使用率排序,则可以按下【M】, 若要回复则按下【P】即可。如果想要离开 top 则按下【q】
#范例二:我们自己的 bash PID 可由 $$ 变量取得,请使用 top 持续观察该 PID
[root@localhost ~]# echo $$
27971
[root@localhost ~]# top -d 2 -p 27971
top - 10:46:17 up 16:46, 3 users, load average: 0.00, 0.01, 0.05
Tasks: 1 total, 0 running, 1 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
KiB Mem : 995676 total, 86144 free, 711236 used, 198296 buff/cache
KiB Swap: 2097148 total, 2024188 free, 72960 used. 106092 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
27971 root 20 0 116460 2920 1660 S 0.0 0.3 0:00.04 bash
3.1.4 pstree
[root@localhost ~]# pstree [-A|U] [-up]
选项与参数:
-A :各程序树之间的连接以 ASCII 字符来连接;
-U :各程序树之间的连接以万国码的字符来连接。在某些终端接口下可能会有错误;
-p :并同时列出每个 process 的 PID;
-u :并同时列出每个 process 的所属帐号名称。
范例一:列出目前系统上面所有的程序树的相关性:
[root@study ~]# pstree -A
systemd-+-ModemManager---2*[{ModemManager}] # 这行是 ModenManager 与其子程序
|-NetworkManager---3*[{NetworkManager}] # 前面有数字,代表子程序的数量!
....(中间省略)....
|-sshd---sshd---sshd---bash---bash---sudo---su---bash---pstree <==我们指令执行的相依性
....(下面省略)....
# 注意一下,为了节省版面,所以鸟哥已经删去很多程序了!
范例二:承上题,同时秀出 PID 与 users
[root@study ~]# pstree -Aup
systemd(1)-+-ModemManager(745)-+-{ModemManager}(785)
| `-{ModemManager}(790)
|-NetworkManager(870)-+-{NetworkManager}(907)
| |-{NetworkManager}(911)
| `-{NetworkManager}(914)
....(中间省略)....
|-sshd(1326)---sshd(13923)---sshd(13927,dmtsai)---bash(13928)---bash(13970)---
....(下面省略)....
# 在括号 () 内的即是 PID 以及该程序的 owner 喔!一般来说,如果该程序的所有人与父程序同,
# 就不会列出,但是如果与父程序不一样,那就会列出该程序的拥有者!看上面 13927 就转变成 dmtsai 了
范例一:列出目前系统上面所有的程序树的相关性:
[root@localhost ~]# pstree -A
systemd-+-ModemManager---2*[{ModemManager}]
|-NetworkManager-+-dhclient
| `-2*[{NetworkManager}]
....(中间省略)....
|-gdm-+-X---{X}
| |-gdm-session-wor-+-gnome-session-b-+-abrt-ap+
| | | |-gnome-s+
....(下面省略)....
范例二:承上题,同时秀出 PID 与 users
[root@localhost ~]# pstree -Aup
systemd(1)-+-ModemManager(593)-+-{ModemManager}(606)
| `-{ModemManager}(624)
|-NetworkManager(793)-+-dhclient(27255)
| |-{NetworkManager}(798)
| `-{NetworkManager}(802)
....(中间省略)....
|-gdm(1141)-+-X(1281)---{X}(1430)
| |-gdm-session-wor(1829)-+-gnome-session-b(1862,mcb)-+-abrt-applet(2387)-+-{abrt-applet}(2398)
| | | | `-{abrt-applet}(2400)
| | | |-gnome-shell(2057)-+-ibus-daemon(2082)-+-ibus-dco+
....(下面省略)....
由 pstree 的输出我们也可以很清楚的知道,所有的程序都是依附在 systemd 这支程序下面的! 仔细看一下,这支程序的 PID 是一号!因为他是由 Linux 核心所主动调用的第一支程序!所以 PID 就是一号了;
3.2 进程的管理
主要的信号代号与名称对应及内容是
代号 | 名称 | 内容 |
1 | SIGHUP | 启动被终止的程序,可让该 PID 重新读取自己的配置文件,类似重新启动 |
2 | SIGINT | 相当于用键盘输入 [ctrl]-c 来中断一个程序的进行 |
9 | SIGKILL | 代表强制中断一个程序的进行,如果该程序进行到一半, 那么尚未完成的部分可能会有“半产品”产生,类似 vim会有 .filename.swp 保留下来。 |
15 | SIGTERM | 以正常的结束程序来终止该程序。由于是正常的终止, 所以后续的动作会将他完成。不过,如果该程序已经发生问题,就是无法使用正常的方法终止时, 输入这个 signal 也是没有用的。 |
19 | SIGSTOP | 相当于用键盘输入 [ctrl]-z 来暂停一个程序的进行 |
3.2.1 kill -signal PID
kill 后面直接加数字与加上 %number 的情况是不同的;
例题:以 ps 找出 rsyslogd 这个程序的 PID 后,再使用 kill 传送讯息,使得 rsyslogd 可以重新读取配置文件。
答:由于需要重新读取配置文件,因此 signal 是 1 号。至于找出 rsyslogd 的 PID 可以是这样做:
ps aux | grep 'rsyslogd' | grep -v 'grep'| awk '{print $2}'
接下来则是实际使用 kill -1 PID,因此,整串指令会是这样:
kill -SIGHUP $(ps aux | grep 'rsyslogd' | grep -v 'grep'| awk '{print $2}')
如果要确认有没有重新启动 syslog ,可以参考登录文件的内容,使用如下指令查阅:
tail -5 /var/log/messages
如果你有看到类似“Aug 5 01:25:02 study rsyslogd: [origin software="rsyslogd" swVersion="7.4.7" x-pid="742" x-info="The rocket-fast Syslog Server - rsyslog"] rsyslogd was HUPed”之类的字样,就是表示 rsyslogd 在 8/5 有重新启动 (restart) 过了!
3.2.2 killall -signal 命令名称
killall是利用【执行命令的名称】来给予信号,而kill则是利用执行命令的PID来给予信号,这是二者最大的不同;
[root@localhost ~]# killall [-iIe] [command name]
选项与参数:
-i :interactive 的意思,互动式的,若需要删除时,会出现提示字符给使用者;
-e :exact 的意思,表示“后面接的 command name 要一致”,但整个完整的指令
不能超过 15 个字符。
-I :指令名称(可能含参数)忽略大小写。
//范例一:给予 rsyslogd 这个命令启动的 PID 一个 SIGHUP 的信号
[root@localhost ~]# killall -1 rsyslogd
//范例二:强制终止所有以 httpd 启动的程序 (其实并没有此程序在系统内)
[root@localhost ~]# killall -9 httpd
//范例三:依次询问每个 bash 程序是否需要被终止运行!
[root@localhost ~]# killall -i -9 bash
信号 bash(2632) ? (y/N) n
信号 bash(27338) ? (y/N) n
信号 bash(27971) ? (y/N) n
bash: no process found
3.3 进程的执行顺序
3.3.1 Priority和Nice值
无优先级的进程队列示意图
具有优先级的进程队列示意图
如上图所示,具高优先权的 pro1, pro2 可以被取用两次,而较不重要的 pro3, pro4 则运行次数较少。 如此一来 pro1, pro2 就可以较快被完成
PRI 值越低代表越优先。不过这个 PRI 值是由核心动态调整的, 使用者无法直接调整 PRI 值
可以通过调整nice值来调整进程的优先级,pri与nice的相关性如下:
PRI(new) = PRI(old) + nice
- nice 值可调整的范围为 -20 ~ 19 ;
- root 可随意调整自己或他人程序的 Nice 值,且范围为 -20 ~ 19 ;
- 一般使用者仅可调整自己程序的 Nice 值,且范围仅为 0 ~ 19 (避免一般用户抢占系统资源);
- 一般使用者仅可将 nice 值越调越高,例如本来 nice 为 5 ,则未来仅能调整到大于 5
修改nice值得办法:
- 一开始执行程序就立即给予一个特定的 nice 值:用 nice 指令;
- 调整某个已经存在的 PID 的 nice 值:用 renice 指令
3.3.2 nice :新执行的命令即给予新的 nice 值
[root@localhost ~]# nice [-n 数字] command
选项与参数:
-n :后面接一个数值,数值的范围 -20 ~ 19。
[root@localhost ~]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 27959 27338 0 80 0 - 48520 do_wai pts/0 00:00:00 su
4 S 0 27971 27959 0 80 0 - 29115 do_wai pts/0 00:00:00 bash
4 T 0 50414 27971 0 75 -5 - 36812 do_sig pts/0 00:00:00 vim
0 R 0 50452 27971 0 80 0 - 38331 - pts/0 00:00:00 ps
# 原本的 bash PRI 为 80 ,所以 vim 默认应为 80。不过由于给予 nice 为 -5 ,
# 因此 vim 的 PRI 降低了!RPI 与 NI 各减 5 !但不一定每次都是正好相同!因为核心会动态调整
[root@localhost ~]# kill -9 %1 <==测试完毕将 vim 关闭
[1]+ 已停止 nice -n -5 vim
3.3.3 renice :已存在进程的 nice 重新调整
[root@localhost ~]# renice [number] PID
选项与参数:
PID :某个程序的 ID !
#范例一:找出自己的 bash PID ,并将该 PID 的 nice 调整到 -5
[root@localhost ~]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 27959 27338 0 80 0 - 48520 do_wai pts/0 00:00:00 su
4 S 0 27971 27959 0 80 0 - 29166 do_wai pts/0 00:00:00 bash
0 R 0 51018 27971 0 80 0 - 38331 - pts/0 00:00:00 ps
[root@localhost ~]# renice -5 27971
27971 (进程 ID) 旧优先级为 0,新优先级为 -5
[root@localhost ~]# ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
4 S 0 27959 27338 0 80 0 - 48520 do_wai pts/0 00:00:00 su
4 S 0 27971 27959 0 75 -5 - 29166 do_wai pts/0 00:00:00 bash
0 R 0 51541 27971 0 75 -5 - 38331 - pts/0 00:00:00 ps
虽然修改的是 bash 那个程序,但是该程序所触发的 ps 指令当中的 nice 也会继承而为 -5 !整个 nice 值是可以在父程序 --> 子程序之间传递
3.4 查看系统资源信息
3.4.1 free :察看内存使用情况 P533
[root@localhost ~]# free [-b|-k|-m|-g|-h] [-t] [-s N -c N]
选项与参数:
-b :直接输入 free 时,显示的单位是 KBytes,我们可以使用 b(Bytes), m(MBytes)
k(KBytes), 及 g(GBytes) 来显示单位喔!也可以直接让系统自己指定单位 (-h)
-t :在输出的最终结果,显示实体内存与 swap 的总量。
-s :可以让系统每几秒钟输出一次,不间断的一直输出的意思!对于系统观察挺有效!
-c :与 -s 同时处理~让 free 列出几次的意思~
范例一:显示目前系统的内存容量
[root@localhost ~]# free -m
total used free shared buff/cache available
Mem: 972 664 99 15 207 126
Swap: 2047 71 1976
3.4.2 uname:查看系统与内核相关信息 P533
uname 可以列出目前系统的内核版本、硬件架构以及 CPU 类型等信息。
[root@localhost ~]# uname [-asrmpi]
选项与参数:
-a :所有系统相关的信息,包括下面的数据都会被列出来;
-s :系统核心名称
-r :核心的版本
-m :本系统的硬件名称,例如 i686 或 x86_64 等;
-p :CPU 的类型,与 -m 类似,只是显示的是 CPU 的类型!
-i :硬件的平台 (ix86)
范例一:输出系统的基本信息
[root@localhost ~]# uname -a
Linux localhost.localdomain 3.10.0-1160.el7.x86_64 #1 SMP Mon Oct 19 16:18:59 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
3.4.3 uptime:查看系统启动时间与任务负载
显示出目前系统已经开机多久的时间,以及 1, 5, 15 分钟的平均负载,相当于显示top界面的最上面一行;
[root@localhost ~]# uptime
09:54:40 up 6:08, 3 users, load average: 0.00, 0.01, 0.05
3.4.4 netstat :追踪网络或socket P535
netstat常被用在网络的监控方面
[root@study ~]# netstat -[atunlp]
选项与参数:
-a :将目前系统上所有的连接、监听、Socket 数据都列出来
-t :列出 tcp 网络封包的信息
-u :列出 udp 网络封包的信息
-n :不以进程的服务名称,以端口号 (port number) 来显示;
-l :列出目前正在网络监听 (listen) 的服务;
-p :列出该网络服务的程序 PID
//范例一:列出目前系统已经创建的网络连线与 unix socket 状态
[root@localhost ~]# netstat
Active Internet connections (w/o servers) #与网络较相关的地方
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 64 localhost.localdoma:ssh 192.168.64.1:54469 ESTABLISHED
Active UNIX domain sockets (w/o servers) #与本机进程较相关的地方
Proto RefCnt Flags Type State I-Node Path
unix 3 [ ] DGRAM 9145 /run/systemd/notify
unix 2 [ ] DGRAM 9147 /run/systemd/cgroups-agent
unix 5 [ ] DGRAM 9168 /run/systemd/journal/socket
.....(下面省略).......
因特网络连线情况的部分:
- Proto :网络的封包协议,主要分为 TCP 与 UDP 封包,相关数据请参考服务器篇;
- Recv-Q:非由用户进程连接到此 socket 的复制的总 Bytes 数;
- Send-Q:非由远程主机传送过来的 acknowledged 总 Bytes 数;
- Local Address :本地端的 IP:port 情况
- Foreign Address:远程主机的 IP:port 情况
- State :连接状态,主要有建立(ESTABLISED)及监听(LISTEN);
socket file 可以沟通两个程序之间的信息,因此程序可以取得对方传送过来的数据
socket file 的输出字段有:
- Proto :一般就是 unix ;
- RefCnt:连接到此 socket 的进程数量;
- Flags :连线的标识;
- Type :socket 存取的类型。主要有确认连线的 STREAM 与不需确认的 DGRAM 两种;
- State :若为 CONNECTED 表示多个进程之间已经建立连接。
- Path :连接到此 socket 的相关进程的路径!或者是相关数据输出的路径
//范例二:找出目前系统上已在监听的网络连线及其 PID
[root@localhost ~]# netstat -tulnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 586/rpcbind
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1128/sshd
tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN 1126/cupsd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1425/master
tcp6 0 0 :::111 :::* LISTEN 586/rpcbind
tcp6 0 0 :::22 :::* LISTEN 1128/sshd
tcp6 0 0 ::1:631 :::* LISTEN 1126/cupsd
tcp6 0 0 ::1:25 :::* LISTEN 1425/master
udp 0 0 0.0.0.0:5353 0.0.0.0:* 578/avahi-daemon: r
udp 0 0 0.0.0.0:753 0.0.0.0:* 586/rpcbind
udp 0 0 0.0.0.0:51113 0.0.0.0:* 578/avahi-daemon: r
udp 0 0 0.0.0.0:67 0.0.0.0:* 1313/dnsmasq
udp 0 0 0.0.0.0:68 0.0.0.0:* 7145/dhclient
udp 0 0 0.0.0.0:111 0.0.0.0:* 586/rpcbind
udp6 0 0 :::753 :::* 586/rpcbind
udp6 0 0 :::111 :::* 586/rpcbind
# 除了可以列出监听网络的接口与状态之外,最后一个字段还能够显示此服务的
# PID 号码以及程序的指令名称喔!例如上头的 1128 就是该 PID
//范例三:将上述的 0.0.0.0:51113 那个网络服务关闭的话?
[root@localhost ~]# kill -9 578
[root@localhost ~]# killall -9 avahi-daemon
3.4.5 dmesg :分析内核产生的信息
因为信息实在太多了,所以执行时可以加入这个管道命令【| more】来使界面暂停
//范例一:输出所有的核心开机时的信息
[root@localhost ~]# dmesg | more
//范例二:搜寻开机的时候,硬盘的相关信息为何?
[root@localhost ~]# dmesg | grep -i sda
[ 2.067052] sd 0:0:0:0: [sda] 41943040 512-byte logical blocks: (21.4 GB/20.0 GiB)
[ 2.067080] sd 0:0:0:0: [sda] Write Protect is off
[ 2.067082] sd 0:0:0:0: [sda] Mode Sense: 61 00 00 00
[ 2.067124] sd 0:0:0:0: [sda] Cache data unavailable
[ 2.067125] sd 0:0:0:0: [sda] Assuming drive cache: write through
[ 2.068351] sda: sda1 sda2 sda3
.......省略......
3.4.6 vmstat :检测系统资源变化 P536
想要了解一个繁忙的系统到底是哪个环节最累人, 可以使用 vmstat 进行分析
[root@study ~]# vmstat [-a] [延迟 [总计检查次数]] <==CPU/内存等信息
[root@study ~]# vmstat [-fs] <==内存相关
[root@study ~]# vmstat [-S 单位] <==设置显示数据的单位
[root@study ~]# vmstat [-d] <==与磁盘有关
[root@study ~]# vmstat [-p 分区] <==与磁盘有关
选项与参数:
-a :使用 inactive/active(活跃与否) 取代 buffer/cache 的内存输出信息;
-f :开机到目前为止,系统复制 (fork) 的程序数;
-s :将一些事件 (启动至目前为止) 导致的内存变化情况列表说明;
-S :后面可以接单位,让显示的数据有单位。例如 K/M 取代 Bytes 的容量;
-d :列出磁盘的读写总量统计表
-p :后面列出分区,可显示该分区的读写总量统计表
//范例一:统计目前主机 CPU 状态,每秒一次,共计三次
[root@localhost ~]# 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
2 0 26740 79636 0 180356 0 1 69 3 65 123 0 0 100 0 0
0 0 26740 79636 0 180388 0 0 0 0 64 117 0 0 100 0 0
0 0 26740 79636 0 180388 0 0 0 0 66 118 0 0 100 0 0
4 特殊文件与进程
4.1 具有 SUID/SGID 权限的命令执行状态
SUID 的程序具有的特点:
- SUID 权限仅对二进制程序(binary program)有效;
- 执行者对于该程序需要具有 x 的可执行权限;
- 本权限仅在执行该程序的过程中有效 (run-time);
- 执行者将具有该程序拥有者 (owner) 的权限。
[dmtsai@study ~]$ passwd
Changing password for user dmtsai.
Changing password for dmtsai
(current) UNIX password: <==这里按下 [ctrl]-z 并且按下 [enter]
[1]+ Stopped passwd
[dmtsai@study ~]$ pstree -uA
systemd-+-ModemManager---2*[{ModemManager}]
....(中间省略)....
|-sshd---sshd---sshd(dmtsai)---bash-+-passwd(root)
| `-pstree
....(下面省略)....
#查询整个系统中的SUID/SGID文件:
[root@localhost ~]# find / -perm /6000
4.2 /proc/* 代表的意义
内存中数据一般写入到/proc/*这个目录下:
[root@localhost ~]# ll /proc
总用量 0
dr-xr-xr-x. 216 root root 0 7月 4 16:50 .
dr-xr-xr-x. 18 root root 237 6月 28 15:53 ..
dr-xr-xr-x. 9 root root 0 7月 4 16:50 1
dr-xr-xr-x. 9 root root 0 7月 6 08:50 10
dr-xr-xr-x. 9 root root 0 7月 6 08:50 10783
.....(中间省略).......
-r--------. 1 root root 0 7月 6 08:55 vmallocinfo
-r--r--r--. 1 root root 0 7月 6 08:55 vmstat
-r--r--r--. 1 root root 0 7月 6 08:55 zoneinfo
主机上面的各个程序的 PID 都是以目录的形式存在于 /proc 当中。如开机所执行的第一支程序 systemd 的 PID 是 1 , 这个 PID 的所有相关信息都写入在 /proc/1/* 当中;
4.3 查询已使用文件或已执行进程使用的文件
4.3.1 fuser:借由文件(或文件系统)找出正在使用该文件的程序
[root@study ~]# 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@localhost ~]# fuser -uv .
用户 进程号 权限 命令
/root: root 7286 ..c.. (root)bash
root 11500 ..c.. (root)bash
ACCESS 的项目代表的意义为:
- c :此程序在当前的目录下(非次目录);
- e :可被触发为执行状态;
- f :是一个被打开的文件;
- r :代表顶层目录 (root directory);
- F :该文件被打开了,不过在等待回应中;
- m :可能为分享的动态函数库;
范例二:找到所有使用到 /proc 这个文件系统的程序吧!
[root@localhost ~]# fuser -uv /proc
用户 进程号 权限 命令
/proc: root kernel mount (root)/proc
rtkit 582 .rc.. (rtkit)rtkit-daemon
# 数据量还不会很多,虽然这个目录很繁忙~没关系!我们可以继续这样作,看看其他的程序!
[root@localhost ~]# fuser -mvu /proc
用户 进程号 权限 命令
/proc: root kernel mount (root)/proc
root 1 f.... (root)systemd
root 374 f.... (root)systemd-journal
......(中间省略).......
mcb 2095 f.... (mcb)gvfs-udisks2-vo
mcb 2227 f.... (mcb)gsd-housekeepin
mcb 2305 f.... (mcb)gvfsd-trash
# 有这几支程序在进行 /proc 文件系统的存取喔!这样清楚了吗?
范例三:找到所有使用到 /home 这个文件系统的程序吧!
[root@localhost ~]# echo $$
11500 # 先确认一下,自己的 bash PID 号码
[root@localhost ~]# cd /home
[root@localhost home]# fuser -muv .
用户 进程号 权限 命令
/home: root kernel mount (root)/
root 1 .rce. (root)systemd
......(中间省略).......
root 11500 .rce. (root)bash # 自己的 PID
[root@localhost ~]# umount /home
umount: /home: target is busy.
(In some cases useful info about processes that use
the device is found by lsof(8) or fuser(1))
# 从 fuser 的结果可以知道,总共有五只 process 在该目录下运行,那即使 root 离开了 /home,
# 当然还是无法 umount 的!那要怎办?哈哈!可以通过如下方法一个一个删除~
[root@localhost ~]# fuser -mki /home
/home: 31535c 31571c 31737c # 你会发现, PID 跟上面查到的相同!
Kill process 31535 ? (y/N) # 这里会问你要不要删除!当然不要乱删除,通通取消!
4.3.2 lsof :列出被程序所打开的文件文件名 P542
与fuser相反,lsof是查出某个进程开启或使用的文件与设备;
[root@localhost ~]# lsof [-aUu] [+d]
选项与参数:
-a :多项数据需要“同时成立”才显示出结果时!
-U :仅列出 Unix like 系统的 socket 文件类型;
-u :后面接 username,列出该使用者相关程序所打开的文件;
+d :后面接目录,亦即找出某个目录下面已经被打开的文件!
范例一:列出目前系统上面所有已经被打开的文件与设备:
[root@localhost ~]# lsof
COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME
systemd 1 root cwd DIR 253,0 4096 128 /
systemd 1 root rtd DIR 253,0 4096 128 /
systemd 1 root txt REG 253,0 1230920 967763 /usr/lib/systemd/systemd
....(下面省略)....
# 在默认的情况下, lsof 会将目前系统上面已经打开的
# 文件全部列出来;所以,可以注意到,第一个文件 systemd 执行的
# 地方就在根目录,而根目录所在的 inode 也有显示出来!
4.3.3 pidof :找出某个正在执行的进程的 PID
[root@study ~]# pidof [-sx] program_name
选项与参数:
-s :仅列出一个 PID 而不列出所有的 PID
-x :同时列出该 program name 可能的 PPID 那个程序的 PID
范例一:列出目前系统上面 systemd 以及 rsyslogd 这两个程序的 PID
[root@localhost ~]# pidof systemd rsyslogd
1 1130
5 SELinux (P543)
SELinux是安全强化的linux之意;
自主访问控制与强制访问控制的区别:
左图是没有 SELinux 的 DAC 存取结果,apache 这个 root 所主导的程序,可以在这三个目录内作任何文件的新建与修改;右边则是加上 SELinux 的 MAC 管理的结果,SELinux 仅会针对 Apache 这个【进程】开放部分的目录, 其他的非正规目录就不会让Apache 使用!因此不管你是谁,就是不能穿透 MAC 的框框;
SELinux 重点在保护进程读取文件系统的权限
主体与目标的安全上下文必须一致才能够顺利读写;
# 再来观察一下系统“程序的 SELinux 相关信息”
[root@localhost ~]# ps -eZ
LABEL PID TTY TIME CMD
system_u:system_r:init_t:s0 1 ? 00:00:04 systemd
system_u:system_r:kernel_t:s0 2 ? 00:00:00 kthreadd
system_u:system_r:kernel_t:s0 4 ? 00:00:00 kworker/0:0H
......(中间省略)......
system_u:system_r:local_login_t:s0-s0:c0.c1023 2855 ? 00:00:00 login
unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 7214 tty2 00:00:00 bash
# 基本上程序主要就分为两大类,一种是系统有受限的 system_u:system_r,另一种则可能是用户自己的,
# 比较不受限的程序 (通常是本机用户自己执行的程序),亦即是 unconfined_u:unconfined_r 这两种!