# 管理进程
# 查看进程
# ps
$ ps # 列出当前终端的进程信息,每行一个进程
[pid] # 只显示指定 pid 的进程的信息
-e # 等价于 -A ,显示系统的所有进程
-f # full ,显示详细信息,包括 PPID
-o pid,lstart,etime,cmd # 指定显示的列,其中 lstart 为启动时刻,etime 为运行时长
-L # 每行一个线程,增加显示 LWP、NLWP 列
-T # 每行一个线程,增加显示 SPID 列。不能与 -L 选项同时使用
a # 显示所有终端启动的进程
f # 将 command 显示成树状
r # 只显示运行中的进程
u # 面向 user 的格式(与 top 的显示格式类似)
x # 增加显示没有控制终端的进程
Z # 增加显示一列安全上下文
安装:
yum install procps
例:
ps auxf # 显示所有进程的详细信息,并且将 command 显示成树状 ps -ef # 显示所有进程的详细信息
例:
[root@CentOS ~]# ps auxf USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 2 0.0 0.0 0 0 ? S 2019 0:02 [kthreadd] root 3 0.0 0.0 0 0 ? S 2019 0:40 \_ [ksoftirqd/0] root 5 0.0 0.0 0 0 ? S< 2019 0:00 \_ [kworker/0:0H] root 7 0.0 0.0 0 0 ? S 2019 0:01 \_ [migration/0]
每列的含义:
- USER :启动进程的用户名。
- PID :进程的 ID 。
- %CPU :进程的 CPU 使用率。
- %MEM :进程的内存使用率。
- VSZ :Virtual Set Size ,虚拟内存。
- RSS :Resident Set Size ,常驻内存。
- TTY :启动进程的终端。
- TTY 为 ? 表示该进程不是从任何终端启动的。
- STAT :进程的运行状态。除了 R(Running)、 S(Sleeping)等常见状态,还可能添加以下标识符:
s # 该进程是 Session Leader + # 该进程属于前台进程 L # 已锁定物理内存 pages l # 该进程包含多个线程 < # 优先级高,即 nice 谦让值低 N # 优先级低,即 nice 谦让值高
- START :进程的启动时刻。
- TIME :进程占用的 CPU 时长,精确到秒。
- 注意它不表示进程的运行时长。因为进程运行时,不一定占用 CPU 。
- COMMAND :进程的启动命令。
- 用方括号包住的 COMMAND 表示内核线程。例如
[kworker/0]
表示运行在 0 号 CPU 上的 kworker 进程。
- 用方括号包住的 COMMAND 表示内核线程。例如
一些额外的列:
- SPID :表示 TID 。
- LWP :表示 TID 。
- NLWP :表示该进程中的线程数。
# pstree
$ pstree # 显示进程树。不过默认将名字相同的进程折叠起来,只计数
[pid] # 显示指定进程的所有子进程。默认指定的 PID 为 1
[user] # 显示指定用户的所有进程
-a # 增加显示每个 command 的命令行参数
-p # 增加显示 PID、TID ,这会展开显示每个进程中的线程
- 安装:
yum install psmisc
# pidof
$ pidof <进程名> # 显示与该名字相同的所有进程的 PID
# 后台进程
- 执行命令时,
- 在命令末尾加上
&
,会将该命令移到后台执行,作为后台任务(job)。 - 按
Ctrl + Z
,会向当前进程发送 SIGSTOP 信号,让它暂停执行,并移到后台任务列表中。
- 在命令末尾加上
- 每个后台任务是一个进程组,有一个任务编号 n 。
- 后台任务不会读取当前终端的 stdin ,但会输出到 stdout 。
- 不同终端的后台任务列表相互独立。
- 如果当前终端退出,则后台任务会因为 Process Session 终止而被杀死。
# jobs
$ jobs # 显示所有后台任务
-l # 增加显示 PID
-p # 只显示 PID
- 例:
[root@CentOS ~]$ nohup ping baidu.com & [1] 8646 nohup: ignoring input and appending output to ‘nohup.out’ [root@CentOS ~]$ jobs -l [1]+ 8646 Running nohup ping baidu.com &
# bg
$ bg <n> # 启动一个已暂停的后台任务
# fg
$ fg <n> # 将一个后台任务移到前台运行
# wait
$ wait [n]... # 阻塞当前终端,直到指定子进程终止
- 如果指定了 n ,则必须存在 PID 等于 n 的进程,而且它是当前终端的子进程。
- 如果不指定 n ,则会等待当前终端的所有子进程运行结束。
- 如果指定了 %n 的格式,则表示某个编号的后台任务,等待其中的进程全部终止。
- 例:
[root@CentOS ~]$ wait 1 -bash: wait: pid 1 is not a child of this shell [root@CentOS ~]$ wait %2 -bash: wait: %2: no such job
# 终止进程
# kill
$ kill
<PID> # 终止进程(默认是向进程发送 SIGTERM 信号)
-kill <PID> # 向进程发送 SIGKILL 信号(这会强制终止进程)
-9 <PID> # 向进程发送编号为 9 的信号
-l # 列出所有可用的信号
# pkill
$ pkill <pattern> # 终止所有进程名与 pattern 匹配的进程
-e # echo what is killed
-9 # 向进程发送信号 9
-t -9 <tty> # 终止指定终端的所有进程
# 保持进程运行
# nohup
:用于以不挂断(no hang up)的方式执行一条命令。
- 运行的命令会忽略 SIGHUP 信号,还会忽略 stdin 。
- 默认将 stdout、stderr 保存到 ./nohup.out 文件中。
- 用法:
nohup <command> nohup <command> & # 将进程移到后台运行,以免阻塞前台。此时默认将输出重定向到 nohup.out 文件,相当于执行 nohup <command> &>> nohup.out &
- 下例是一个重启进程的脚本:也可改为根据 PID 终止进程:
# 该脚本名为 restart.sh ,用于根据启动命令杀死进程,再用 nohup 重启。 # 使用该脚本之前,需要将 CMD 变量设置为进程的启动命令 # 使用该脚本时,只需执行 sh restart.sh CMD="ping localhost" # 该脚本应该放在进程的工作目录下。每次执行脚本时,先切换到脚本所在目录 WORK_DIR=$(cd $(dirname $0); pwd) cd $WORK_DIR # 如果有相同进程正在运行,则全部杀死 PID=`ps auxf | grep "$CMD" | grep -v grep | awk '{print $2}' | xargs` if [ "$PID" ]; then echo "The process is running, sending SIGTERM to PID: $PID" kill $PID sleep 5 # 如果进程依然存在,则强制杀死 PID=`ps $PID | awk 'NR>1 {print $1}' | xargs` if [ "$PID" ]; then echo "The process is still running, sending SIGKILL to PID: $PID" kill -9 $PID sleep 1 fi fi # 重新启动进程 nohup $CMD &>> $(date +%Y%m%d-%H%M%S).log & echo "Started process: $CMD"
PID_FILE=$WORK_DIR/pid if [ -f $PID_FILE ]; then kill `cat $PID_FILE` fi nohup $CMD &>> $(date +%Y%m%d-%H%M%S).log & echo $! > $PID_FILE
# screen
:可以创建多个连接到当前终端的 Session 。即使用户退出了终端,该终端也依然有 Session 存在,不会被系统终止。
已淘汰不用
- 安装:
yum install screen
- 被 screen 连接的会话记作 attached 状态,没被连接的则记作 detached 状态。
- 命令:
$ screen # 创建一个新会话,并进入其 shell -ls # 列出所有会话 -dm # 创建一个脱离的新会话 -r <pid> # 连接到一个脱离的会话 -s <shell> # 指定使用的 shell -S <name> # 指定会话的名字(这会命名为<pid>.<name>,默认的命名为<pid>.<tty>.<host>) -L # 自动将该会话的终端日志记录到/home/screenlog.0 文件中(数字会递增)
# tmux
:一个与 screen 类似的工具,但功能更强。
安装:
yum install tmux
只需创建一个连接到当前终端的 Session ,然后在该 Session 中创建多个窗口,每个窗口是一个伪终端。
- 每个窗口还可以拆分成多个面板。
- 不同用户的 tmux 窗口互不可见。
命令:
$ tmux # 创建一个新窗口,并进入 new # 创建一个新窗口,并进入 -s <name> # 设置窗口的名字(不指定的话就使用数字编号) -d # 在后台创建 ls # 显示所有窗口 a # 进入(attach)上一个窗口 a -t <name> # 进入指定的窗口 kill-session -t <name> # 终止指定的窗口 send -t <name> "command" ENTER # 向一个窗口输入一条命令,再输入 ENTER
进入 tmux 界面之后,
- 不能在里面创建窗口。
- tmux 界面的下方会显示一个绿色的任务栏,包含一排窗口名,其中有星号 * 后缀的是当前窗口。
- 例如,下方的信息表示:目前在名为“4”的会话中,有编号 1~4 四个窗口,都名为 bash 。目前正在使用窗口“3:bash”,上一个窗口是窗口“2:bash”。
[4] 0:bash 1:bash 2:bash- 3:bash*
- 按 Ctrl+D 会退出当前的窗口或面板。
- 按 Ctrl+B 会激活控制台,然后便可以输入以下命令:
d # 将 tmux 挂到后台(显示 detached) s # 打开会话列表,从而切换到某个会话 $ # 重命名当前会话 w # 打开窗口列表,从而切换到某个窗口 n # 选择下一个窗口 p # 选择上一个窗口 c # 创建一个新窗口 , # 重命名当前窗口 . # 修改当前窗口的编号(这会重新排序) [ # 进入阅读模式,可以滚屏、翻页 " # 将当前面板拆分成上下两块 % # 将当前面板拆分成左右两块 方向键 # 切换面板 空格键 # 切换面板布局 ! # 将当前面板置于新窗口中 ? # 显示快捷键
例:启动 tmux 之后的进程树
root 3907 0.0 0.1 24248 3696 ? Ss Nov08 2:36 tmux root 3908 0.0 0.1 116484 3040 pts/1 Ss Nov08 0:00 \_ -bash root 24224 0.0 2.3 282340 43536 pts/1 S+ 14:37 0:00 | \_ ping 127.0.0.1 root 31780 0.0 0.1 116096 2604 pts/4 Ss+ 17:25 0:00 \_ -bash root 31854 0.2 0.1 116096 2604 pts/5 Ss+ 17:26 0:00 \_ -bash root 3057 0.0 0.0 112860 1272 ? Ss Sep10 0:00 /usr/sbin/sshd -D root 32653 0.0 0.2 156740 5444 ? Ss 17:44 0:00 \_ sshd: root@pts/3 root 32656 0.2 0.1 116100 2632 pts/3 Ss 17:44 0:00 \_ -bash root 32695 0.0 0.1 155496 1928 pts/3 R+ 17:44 0:00 \_ ps auxf
- 可见 tmux 创建了三个伪终端,运行在独立的 Session 中。