监控和管理Linux进程

什么是进程?

进程是已启动的可执行程序的运行中实例。一个程序可能会有好几个进程。进程有以下组成部分:

  • 已分配内存的地址空间;
  • 安全属性,包括所有权凭证和特权;
  • 程序代码的一个或多个执行线程;
  • 进程状态

进程的环境包括:

  • 本地和全局变量;
  • 当前调度上下文;
  • 分配的系统资源,如文件描述符和网络端口;

现有的(父)进程复制自己的地址空间(fork复刻、分支)来创建一个新的(子)进程。每个新进程分配有一个唯一进程ID(PID),满足跟踪和安全性之需。PID和父进程ID(PPID)是新进程环境的元素。任何进程可创建子进程。所有进程都是一个系统进程的后代,在RHEL7系统上,第一个系统进程是systemd(1)。

通过fork历程,子进程继承安全性身份、过去和当前的文件描述符、端口和资源特权、环境变量以及程序代码。随后,子进程可能exexc其自己的程序代码。通常父进程在子进程运行期间处于睡眠状态,设置一个在子进程完成时发出信号的请求(wait)。在退出时,子进程可能已经关闭或者丢弃了其资源和环境;剩余的部分称为僵停。父进程在子进程退出时收到信号而被唤醒,清理剩余的进程结构,然后继续执行自己的程序代码。

进程状态

在多任务处理操作系统中,每个CPU(或CPU核心)在一个时间点上处理一个进程。在进程运行时,它对CPU时间和资源分配的直接要求会有变化。进程分配有一个状态,它随着环境要求而发生变化。

进程状态

名称标志内核定义的状态名称和描述
运行中RTASK_RUNNING:进程正在CPU上执行,或者正在等待运行。处于运行中(或可运行)状态时,进程可能正在执行用户例程或内核例程(系统调用),或者已配对并就绪。
睡眠STASK_INTERRUPTIBLE:由于进程未获得它所申请的资源而处于等待状态,进程正在等待某一条件:硬件请求、系统资源访问、或者唤醒信号。当事件或者信号满足该条件时,该进程将返回到运行中。
睡眠DTASK_UNINTERRUPTIBLE:此进程也在睡眠,但与S状态不同,不会响应传递的唤醒信号,只有当它申请的资源有效时才能被唤醒。
睡眠KTASK_KILLABLE:与不可中断的D状态相同,但有所修改,允许等待中的任务通响应信号而被中断(彻底退出)。实用程序通常将可中断的进程显示为D状态。
已停止TTASK_STOPED:进程已被停止(暂停),通常是通过用户或其他进程发出一个SIGSTOP信号后,就由运行状态进入停止状态,当收到一个SIGCONT信号时,又会恢复运行状态,这种状态主要用于程序的调试。
已停止TTASK_TRACED:正在被调试的进程也会临时停止,并且共享一个T状态标志。
僵停ZEXIT_ZOMBIL:进程在退出过程中,处于该状态,在这个退出过程中,进程占有的资源将被回收,除了进程结构。于是只剩下进程结构这么可空壳,所以是僵尸状态。之所以保留进程结构,是因为进程结构中保存了进程的退出码、以及一些统计信息,而父进程可能会关心这些信息。
僵停XEXIT_DEAD:当父进程清理剩余的子进程结构时,进程现在已彻底释放。此状态基本不会在进程列表中被捕捉到。

列出进程

ps命令用于列出当前的进程。该命令可以提供详细的进程信息,包括:

  • 用户标识符(UID),它确定进程的特权;
  • 唯一进程标识符(PID);
  • CPU和已经花费的实际时间;
  • 进程在各种位置上分配的内存数量;
  • 进程的位置STDOUT,称为控制终端;
  • 当前的进程状态;

常用显示列表(选项 aux)显示所有进程,包含用户感兴趣的列,以及没有控制终端的进程。长列表(lax)提供更多技术详细信息,但可通过避免查询用户名来加快显示。相似的UNIX与方法使用(选项 -ef)来显示所有进程。

[root@linuxprobe Desktop]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.2  50504  4260 ?        Ss   11:45   0:01 /usr/lib/syste
root          2  0.0  0.0      0     0 ?        S    11:45   0:00 [kthreadd]
root          3  0.0  0.0      0     0 ?        S    11:45   0:00 [ksoftirqd/0]
root          5  0.0  0.0      0     0 ?        S<   11:45   0:00 [kworker/0:0H]
##省略输出##
[root@linuxprobe Desktop]# 
[root@linuxprobe Desktop]# ps lax
F   UID    PID   PPID PRI  NI    VSZ   RSS WCHAN  STAT TTY        TIME COMMAND
4     0      1      0  20   0  50504  4268 ep_pol Ss   ?          0:01 /usr/lib/systemd/systemd -
1     0      2      0  20   0      0     0 kthrea S    ?          0:00 [kthreadd]
1     0      3      2  20   0      0     0 smpboo S    ?          0:00 [ksoftirqd/0]
1     0      5      2   0 -20      0     0 worker S<   ?          0:00 [kworker/0:0H]
1     0      7      2 -100  -      0     0 smpboo S    ?          0:00 [migration/0]
##省略输出##
[root@linuxprobe Desktop]# 
[root@linuxprobe Desktop]# ps -ef
UID         PID   PPID  C STIME TTY          TIME CMD
root          1      0  0 21:00 ?        00:00:01 /usr/lib/systemd/systemd --swi
root          2      0  0 21:00 ?        00:00:00 [kthreadd]
root          3      2  0 21:00 ?        00:00:00 [ksoftirqd/0]
root          5      2  0 21:00 ?        00:00:00 [kworker/0:0H]
##省略输出##
[root@linuxprobe Desktop]# 

默认情况下,如果不带任何选项执行ps命令,将选择具有与当前用户相同的有效用户ID并与调用ps所处同一终端关联的所有进程。

  • 方括号中的进程(通常位于顶部)为调度的内核线程。
  • 僵停在ps列表中显示为exiting或defunct。
  • ps仅显示一次。如需重复更新进程信息,请运行top命令。
  • 默认的输出没有排序。显示顺序与系统进程表的顺序匹配,在进程终止和新进程创建时重新使用列表行。

控制作业

作业和会话

作业控制是一种命令shell功能,允许单个shell实例运行和管理多个命令。没有作业控制时,shell父级进程分出子进程以运行命令,保持睡眠状态直到子进程退出。当shell提示符重新显示时,父级shell已回归。使用作业控制时,可以选择性的暂停、恢复和异步运行命令,让shell可以在子进程运行期间返回接受其他命令。

前台进程是在终端窗口中正在运行的命令。终端的设备ID(tty)是进程的终端控制。前台进程接收键盘生成的输入和信号,可以从终端读取和写入到终端(如通过stdin和stdout)。

当终端或控制台第一次打开时(例如在登陆时或通过调用新的Terminal实例),创建一个进程会话。从该终端启动的所有进程共享相同的会话ID。会话内,一次仅能由一个进程处于前台。

后台进程是以无控制终端的形式启动的,因为它不需要终端交互。在ps列表中,此类进程将在TTY列中显示一个问号(?)。后台进程如果尝试从终端读取或写入到终端,可能会被暂停。

在后台运行作业

任何命令都可以在后台启动,只需在命令行中加&符号。Bash shell显示作业编号(对于该会话唯一)和新的子进程的PID。命令shell不等待子进程,并且重新显示shell提示符。

[root@linuxprobe Desktop]# sleep 1000 &
[1] 4279
[root@linuxprobe Desktop]# 

注意 &符号仅将管道中的最后一个命令置于后台,除非命令集用括号括起来。返回的PID来自管道的最后一个进程。管道中的所有进程现在是同一作业中的成员。

bash命令shell根据会话跟踪作业,这些作业可以通过jobs命令显示在一张表中:

[root@linuxprobe Desktop]# jobs
[1]+  Running                 sleep 1000 &
[root@linuxprobe Desktop]# 

通过fg命令和作业编号ID将后台作业带到前台,后台作业可以重新和控制终端连接:

[root@linuxprobe Desktop]# jobs
[1]-  Running                 sleep 1000 &
[2]+  Running                 sleep 1003 &
[root@linuxprobe Desktop]# fg %2
sleep 1003

实例中的sleep命令目前在控制终端上运行。命令shell再次睡眠,等待这一子进程退出。若要重新发送到后台,或者发送原先不含结尾&符号的任何命令到后台,可向进程发送键盘生成的暂停请求(Ctrl+z)。

[root@linuxprobe Desktop]# fg 2
sleep 1003
^Z
[2]+  Stopped                 sleep 1003
[root@linuxprobe Desktop]#

暂停将立即起作用。作业将被放到后台。未处理的输出和键盘输入将被丢弃。

ps命令的j选项显示作业信息,如各个会话的初始命令shell。由于示例中的sleep命令当前已暂停,其状态标志将显示为T。

[root@linuxprobe Desktop]# ps j
  PPID    PID   PGID    SID TTY       TPGID STAT   UID   TIME COMMAND
  1213   1236   1236   1236 tty1       1236 Ssl+     0   0:22 /usr/bin/Xorg :0 -
  5189   5193   5193   5193 pts/1      5269 Ss       0   0:00 /bin/bash
  5193   5261   5261   5193 pts/1      5269 T        0   0:00 sleep 1000
  5193   5269   5269   5193 pts/1      5269 R+       0   0:00 ps j
[root@linuxprobe Desktop]# 

要在后台重新启动进程,可使用bg命令及对应的作业编号ID:

[root@linuxprobe Desktop]# jobs
[1]+  Stopped                 sleep 1000
[root@linuxprobe Desktop]# bg 1
[1]+ sleep 1000 &
[root@linuxprobe Desktop]# jobs
[1]+  Running                 sleep 1000 &
[root@linuxprobe Desktop]# 

用户尝试退出带有暂停作业的终端窗口(会话)时,命令shell将发出警告。如果用户再次尝试则立即退出,暂停的作业将被中断。

中断进程

使用信号控制进程

信号是传递至进程的软件中断。信号向执行中的程序报告事件。生成信号的事件可以是错误或外部事件(如I/O请求或计时器过期),或者来自于明确请求(如使用信号发送命令或键盘序列)。

下表列出了系统管理员日常用来管理系统进程的基本信号。我们一般使用短名称(HUP)或正确名称(SIGHUP)指代信号。

基本进程管理信号

信号编号短名称定义用途
1HUP挂起该信号让用于让终端控制进程立即终止。对于与终端脱离关系的守护进程,这个信号用于通知它重新加载配置文件进行重新初始化而不终止。SIGHUP会在以下3中情况下被发送给相应的进程:1、终端关闭时,该信号被发送到session首进程以及作为job提交的进程(即用&符号提交的进程);2、session首进程退出时,该信号被发送到该session中的前台进程组中的每一个进程;3、若父进程退出导致进程成为孤儿进程,且该进程处于停止状态,该信号会被发送到该进程。
2INT键盘中断用于前台进程终止,但是该信号可以被拦截或者处理。相当于键盘Crtl+c
3QUIT键盘退出与SIGINT相似,但是在终止时生成进程转储。相当于键盘Ctrl+\
9KILL中断,无法拦截导致立即终止程序。无法被拦截、忽略或者处理;一般用于强制终止。
15TERM终止导致程序终止。和SIGKILL不同,可以被拦截、忽略或处理。是要求程序终止的友好方式,也是kill命令的默认信号;允许进程自我清理。
18CONT继续该信号可以让暂停状态的进程恢复运行。无法被拦截,即使被处理,也始终会恢复进程。
19STOP停止,无法拦截暂停前台进程。无法被拦截或处理。
20TSTP键盘停止和SIGSTOP不同,可以被拦截、忽略和处理。相当于Ctrl+z

注意:信号编号视不同的Linux硬件平台而异,但是信号名称和含义都是标准化的。作为命令使用时,建议使用信号名称而不是编号。

每个信号都有一个默认操作,通常是如下之一:

  • 终止:导致程序立即终止(退出);
  • 核心转储:导致程序保存内存映像(核心转储),然后终止;
  • 停止:导致程序停止执行(暂停),再等待继续(恢复);

通过明确请求发送信号的命令

用户向当前的前台进程发送信号,具体操作为键入键盘控制序列以暂停Ctrl+z、中断Crtl+c或核心转储Ctrl+\该进程。要向后台进程或另一会话中的进程发送信号,需要使用信号发送命令。

我们可以通过信号名称(如-HUP或-SIGHUP)或编号(如-1)指定信号。用户可以中断自己的进程,但是需要root权限才能够终止其他人拥有的进程。

  • kill命令根据ID向进程发送信号。虽然其名称为kill,但是该命令可以用于发送任何信号,而不仅仅是终止程序的信号。
[root@linuxprobe Desktop]# kill PID
[root@linuxprobe Desktop]# kill -signal PID
[root@linuxprobe Desktop]# kill -l
 1) SIGHUP	 2) SIGINT	 3) SIGQUIT	 4) SIGILL	 5) SIGTRAP
 6) SIGABRT	 7) SIGBUS	 8) SIGFPE	 9) SIGKILL	10) SIGUSR1
11) SIGSEGV	12) SIGUSR2	13) SIGPIPE	14) SIGALRM	15) SIGTERM
16) SIGSTKFLT	17) SIGCHLD	18) SIGCONT	19) SIGSTOP	20) SIGTSTP
21) SIGTTIN	22) SIGTTOU	23) SIGURG	24) SIGXCPU	25) SIGXFSZ
26) SIGVTALRM	27) SIGPROF	28) SIGWINCH	29) SIGIO	30) SIGPWR
31) SIGSYS	34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
63) SIGRTMAX-1	64) SIGRTMAX	
[root@linuxprobe Desktop]# kill
  • 使用killall可以发送信号到一个或多个与选择条件匹配的进程,如命令名称、由特定用户拥有的进程,或者系统范围内的所有进程。
[root@linuxprobe Desktop]# killall command_pattern
[root@linuxprobe Desktop]# killall -signal command_pattern
[root@linuxprobe Desktop]# killall -signal -u username command_pattern
[root@linuxprobe Desktop]# sleep 10001 &
[1] 3216
[root@linuxprobe Desktop]# sleep 10002 &
[2] 3224
[root@linuxprobe Desktop]# sleep 10003 &
[3] 3232
[root@linuxprobe Desktop]# jobs
[1]   Running                 sleep 10001 &
[2]-  Running                 sleep 10002 &
[3]+  Running                 sleep 10003 &
[root@linuxprobe Desktop]# killall sleep
[1]   Terminated              sleep 10001
[2]-  Terminated              sleep 10002
[3]+  Terminated              sleep 10003
[root@linuxprobe Desktop]# jobs
[root@linuxprobe Desktop]# 
  • pkill命令和killall相似,也可以向多个进程发送信号。pkill使用高级选择条件,可包含以下条件的组合:

    命令–具有模式匹配的命令名称的进程。

    UID–由某一Linux用户账户用拥有的进程,无论是有效还是真实的。

    GID–由某一Linux组账户拥有的进程,无论是有效还是真实的。

    父级–特定父进程下的子进程。

    终端–运行于特定控制终端的进程。

[root@linuxprobe Desktop]# pkill command_pattern
[root@linuxprobe Desktop]# pkill -signal command_pattern
[root@linuxprobe Desktop]# pkill -G GID command_pattern
[root@linuxprobe Desktop]# pkill -P PPID connmad_pattern
[root@linuxprobe Desktop]# pkill -t terminal_name -U UID command_pattern

以管理员身份注销用户

w命令可以查看当前登陆系统的用户,以及它们积累的活动。通过TTY和FROM列确定用户的位置。

所有用户都有一个控制终端,在图形环境窗口(虚拟终端)中操作时,TTY列的值显示为pts/N,而通过系统控制台、替代控制台或其他直接连接的终端设备操作时,则该列值为ttyN。使用-f选项时,远程用户在FROM列中显示其系统名称。

[root@linuxprobe Desktop]# w
 20:14:34 up 14 min,  2 users,  load average: 0.16, 0.06, 0.07
USER     TTY        LOGIN@   IDLE   JCPU   PCPU WHAT
root     :0        20:00   ?xdm?   2:12   0.07s gdm-session-worker [pam/gdm-pas
root     pts/0     20:00    2.00s  0.11s  0.03s w
[root@linuxprobe Desktop]# who
root     :0           2019-06-28 20:00 (:0)
root     pts/0        2019-06-28 20:00 (:0)
[root@linuxprobe Desktop]# w -f
 20:15:14 up 15 min,  2 users,  load average: 0.09, 0.05, 0.06
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     :0       :0               20:00   ?xdm?   2:20   0.07s gdm-session-wor
root     pts/0    :0               20:00    2.00s  0.09s  0.00s w -f
[root@linuxprobe Desktop]# 

查看会话登陆事件,了解该用户已经登陆该系统的时长。对于每个会话,由当前作业占用的CPU资源(包括后台任务和子任务占用的)会在JCPU这一列显示。当前的前台进程占用的CPU资源会在PCPU这一列中显示。

用户可能会因为安全性违规、资源分配过度或其他管理需求而被强制从系统注销。用户需要在收到请求时,退出不必要的应用,关闭不使用的命令shell,并退出登陆会话。

注意,虽然SIGTERM是kill命令的默认信号,但是SIGKILL是管理员偏爱但却常常误用的信号。由于SIGKILL信号无法被处理或忽略,它总是致命的。它会强行终止进程,而不允许被中断的进程运行自我清理例程。建议先发送SIGTERM,只有在进程未能响应时再通过SIGKILL重试。

我们可以逐一向进程和会话发送信号,也可以同时发送。要终止一个用户的所有进程,可以使用pkill命令。由于登陆会话中的初始进程(会话首进程)设计为可以处理会话终止请求并忽略不想要的键盘信号,所以要中断某一用户的所有进程和登陆shell时,我们需要使用SIGKILL信号。pgrep命令用来过滤、筛选进程。

[root@linuxprobe Desktop]# pgrep -l -u rwas
4325 bash
4164 sleep
7463 sleep
8333 sleep
[root@linuxprobe Desktop]# pkill -SIGKILL -u rwas
[root@linuxprobe Desktop]# pgrep -l -u rwas
[root@linuxprobe Desktop]#

当需要终止的进程在同一登陆会话中时,可能不需要中断用户的所有进程。这时,我们通过w命令确定会话的控制终端,然后仅中断引用同一终端ID的进程。除非指定了SIGKILL信号,否则的话会话的首进程(此处bash shell)可以成功处理终止请求并保留,但是所有其他会话进程将被终止。

[root@linuxprobe Desktop]# w -h -u rwas
rwas     tty3     20:55    2:28   0.03s  0.03s -bash
[root@linuxprobe Desktop]# pgrep -l -u rwas
4980 sleep
4985 sleep
4991 sleep
5106 sshd
5107 bash
5199 sleep
5200 sleep
[root@linuxprobe Desktop]# pkill -t tty3
[root@linuxprobe Desktop]# pgrep -l -u rwas
5107 bash
[root@linuxprobe Desktop]# pkill -SIGKILL -t tty3
[root@linuxprobe Desktop]# pgrep -l -u rwas
[root@linuxprobe Desktop]#

我们还可以利用父进程和子进程的关系来选择性的终止进程。使用pstree命令查看系统或单个用户的进程树。使用父进程的PID中断其创建的所有子进程。此时,父进程bash登陆shell可以保留,因为信号仅定向至它的子进程。

[root@linuxprobe Desktop]# pstree -p rwas
sshd(5106)───bash(5107)─┬─sleep(5801)
                        ├─sleep(5814)
                        └─sleep(5823)
[root@linuxprobe Desktop]# pkill -P 5107
[root@linuxprobe Desktop]# pgrep -l -u rwas
5106 sshd
5107 bash
[root@linuxprobe Desktop]#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值