Linux进程状态

查看当前运行进程

有许多方式可以查看当前linux系统中的运行进程, 常用的有top, htop 以及 ps 三个命令;

其中htoptop工具具备更好的显示方式:

htop示例

其中上方的CPU和内存信息可以帮助更好地监控整个机器的运行状态, 还提供了一些常用操作的快捷键, 如F5树形结构展示进程树等等;

htop命令的缺点是显示的内容是在一个独立页面中的, 无法通过linux管道做更多的操作, 而且如果进程数量太多的话, 进程的查看就不是那么直观;

使用ps命令可以得到标准输出的格式, ps命令提供了一系列参数以调整输出内容, 具体参数可以通过man ps了解;

为了便于观察, 我经常使用的命令参数为: ps px, 此时会显示5列信息, 依次为:

  • PID: 进程号;
  • TTY: 登陆者编号, 其中tty表示本地登陆者, pts表示远程登陆者;
  • STAT: 进程状态;
  • TIME: 进程运行时间;
  • COMMAND: 树形结构展示的进程对应命令;

除了STAT用不知名字符表示之外(下面讲), 其他列的内容都非常容易理解;

进程状态

linux下的常见状态有:

  • R: 正在运行状态或者在排队中的可运行状态, 如果用ps命令的话一般很难捕获到该状态;
  • S: 睡眠状态, 并且可以被中断;
  • D: 睡眠状态, 并且不能被中断, 该状态通常是由于IO堵塞造成;
  • T: 停止状态, 该状态下, 进程被暂停挂起;
  • Z: 僵尸状态, 该状态的进程已经结束, 但是由于父进程没有回收, 所以显示状态;

除了这些主要状态之外, 通常会发现后面还有一个标识状态, 如某个进程状态为Ss, 主要常见下列标识:

  • <: 高优先级;
  • N: 低优先级;
  • L: 页面锁定在内存;
  • s: 信息头;
  • l: 多线程状态;
  • +: 前台运行组;

在实际应用中, S等状态良民一般不会给我们造成困扰, 主要需要了解如何处理一些棘手的状态;

理解上述状态便于后续对这些状态进程的处理(挂起、恢复、杀死);

操作进程

进程操作可以通过kill命令进行, kill命令可以对进程发出很多的信号, 具体的信号可以参考/usr/include/asm/signal.h头文件(不同系统会有所区别), 最重用的信号有:

  • SIGSTOP: 挂起进程, 进程进入T状态;
  • SIGCONT: 继续进程, 使得T状态的进程重新运行;
  • SIGKILL: 杀死进程;

使用kill -sig [pid]的方式调用, 如需要杀死一个进程号为5477的进程, 则可以使用: kill -SIGKILL 5499来杀死这个进程;

对于一般的任务, 不需要发送信号就可以杀掉进程, 但是如果是想杀死上述所说的T状态进程等, 则必须加上SIGKILL信号; 但是对于D状态进程, 则不推荐强行杀死, 而是等IO重新正常建立之后再杀死, 如检查网络使其正常连接等等;

当进程数量非常多的时候如一个父进程fork出几十个子进程, 如何批量杀死进程呢?

一种方式是用之前提到的管道, 然后通过grep或者各种命令来筛出感兴趣的pid号, 然后使用kill命令集体杀死, 如:

ps fx | grep python | awk '{print $1}' | while read pid; do kill $pid; done

等等;

另外一种方式是递归杀死一颗进程树, 这样可以节省很多工作:

#!/bin/env bash
function killtree() {
    local _pid=$1
    local _sig=${2:-TERM}
    kill -stop ${_pid}
    for _child in $(ps -o pid --no-headers --ppid ${_pid})
    do
       killtree ${_child} ${_sig}
    done
    kill -${_sig} ${_pid}
}

if [ ${#} -eq 0 -o ${#} -gt 2 ]
then
    echo "Usage: $(basename ${0}) <pid> [signal]"
    exit 1
fi

killtree ${@}

以上程序参考网络, 具体哪里忘记了, 如果有侵犯到相关权益, 请告知

将上面的程序命名为killtree, 并赋予x权限, 把该文件放到某个PATH路径下以便系统识别, 如: ~/bin等, 之后就可以使用killtree命令杀死一个进程树了;