当我们 ssh 登录上 Linux shell 之后,在此终端下可以同时执行多个命令或脚本,对这些任务的管理就叫做工作管理
。比如:想要一边复制文件,一边进行数据查找。
job control 进行管理的进程必须是你 shell 的子进程。
01 — &
&
可以直接将命令丢到后台中运行,比如我们要将 /etc/ 整个备份成为 /tmp/etc.tar.gz 且不想要等待,那么可以这样做:
meng➜/tmp» tar -zpcf /tmp/home.tar.gz /home/meng & [21:03:46]
[1] 28270
[1]:是 job number 28270:进程 PID
在后台当中运行的命令,如果有 stdout 及 stderr 时,它的数据依旧是输出到屏幕上面的。所以,佳的状况就是利用数据流重定向, 将输出数据传送至某个文件中。
tar -zpcf /tmp/home.tar.gz /home/meng > /tmp/log.txt 2>&1 &
02 — job 管理
jobs:
列出当前 shell 中执行的 job
meng➜/tmp» jobs [21:03:52]
[1] + running tar -zpcf /tmp/home.tar.gz /home/meng
选项与参数: -l -l :除了列出 job number 与命令串之外,同时列出 PID 的号码; -r -r :仅列出正在后台 run 的工作; -s -s :仅列出正在后台当中暂停 (stop) 的工作。
fg
:将后台工作拿到前景来处理
fg %job_number
比如上面我们通过 & 将打包命令放在了后台执行,通过 jobs 拿到 job number 1,然后通过 fg %1 即可拿到前台来处理。
bg
:让工作在后台下的状态变成运行中
比如上面打包命令,忘记加 & 放后台执行了,这个时候要放到后台执行怎么办呢?
按键 Ctrl + z 将当前工作丢到后台暂停,然后再通过 bg %job_number ,将工作运行。
meng➜/tmp» sh ./task.sh [21:24:51]
^Z
[1] + 28429 suspended sh ./task.sh
meng➜/tmp» jobs [21:24:55]
[1] + suspended sh ./task.sh
meng➜/tmp» bg %1 [21:25:00]
[1] + 28429 continued sh ./task.sh
kill
:管理后台当中的工作
meng➜/tmp» kill %1 [21:25:06]
[1] + 28429 terminated sh ./task.sh
03 — 脱机管理
上面我们讲的命令执行都是在当前 shell 中执行,如果退出 shell 命令都会被关闭掉。你在 shell 中执行的命令,这些命令的父进程都是 shell 进程,当你退出 shell 的时候系统会给 jobs 列出的进程发送信号:SIGHUP,这会导致进程关闭。
通过 ps 可以看到对应进程的父进程(PPID)
meng➜/tmp» ps -ejf| head [21:41:30]
UID PID PPID PGID SID C STIME TTY TIME CMD
root 1 0 1 1 0 Aug20 ? 00:00:17 /sbin/init splash
root 2 0 0 0 0 Aug20 ? 00:00:00 [kthreadd]
root 4 2 0 0 0 Aug20 ? 00:00:00 [kworker/0:0H]
简单讲下 PGID 和 SID
SID:Session Identifier (Session Leader)。当前 shell 进程id,可以通过环境变量输出:
echo $$
PGID:Process Group Identifier (Process Group Leader)。我一次执行多个命令就可以认为是一个 Process Group,Leader 就是取个命令的进程id。
nohup
:让进程忽略掉 SIGHUP 信号。
如下所示,task.sh 的进程对应的父进程是当前 shell 进程。当我们退出终端,重新进入后,父进程就变成了系统的 1 号进程(退出终端后,找不到父进程,这个时候进程就会被挂在 1 号进程下)。
meng➜/tmp» nohup sh ./task.sh & [21:59:56]
[1] 29164
meng➜/tmp» ps -lf [22:00:50]
F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
0 S meng 29063 29062 0 80 0 - 13532 sigsus 21:57 pts/2 00:00:00 -zsh
0 S meng 29164 29063 0 85 5 - 1157 wait 22:00 pts/2 00:00:00 sh ./task.sh
# 退出终端,重新进入
meng➜~» ps -ejf| grep task.sh
UID PID PPID PGID SID C STIME TTY TIME CMD
meng 29164 1 29164 29063 0 22:00 ? 00:00:00 sh ./task.sh
我们已经知道,如果事先在命令前加上 nohup 就可以在你关闭终端后继续运行程序。但是如果我们未加任何处理就已经提交了命令,该如何补救呢。
disown
它可以将指定任务从"后台任务"列表(jobs命令的返回结果)之中移除。一个"后台任务"只要不在这个列表之中, 关闭 shell 的时候肯定不会向它发出SIGHUP 信号。
# 移出近一个正在执行的后台任务
$ disown
# 移出所有正在执行的后台任务
$ disown -r
# 移出所有后台任务
$ disown -a
# 不移出后台任务,但是让它们不会收到SIGHUP信号
$ disown -h
# 根据jobId,移出指定的后台任务
$ disown %2
$ disown -h %2
文章作者|来源:CoderMeng