进程组
当我们在终端中敲下一条命令,然后按下回车的时候,Shell会开启一个新进程来执行这条命令。如果这条命令是由管道连接起来的多个命令组成的话,Shell便会开启多个进程来执行这一组任务。无论是单独的一条命令,还是由管道连接的多条命令,都会被放入到一个新的进程组(任务)中。只包含一条命令的时候,就会创建一个由一个进程组成的进程组。进程组中的每个进程都具有相同的进程组标识符(进程组ID),这个进程组标识符其实就是进程组中某个进程(即进程组组长)的进程ID。
会话
会话指的是一组进程组(任务)。一个会话中的所有进程都具有相同的会话标识符,会话首进程是指创建会话的进程,其进程ID会成为会话ID。使用会话最多的是支持任务控制的shell,由shell创建的所有进程组及shell自身隶属与同一个会话,shell自身就是该会话的会话首进程。
在任意时刻,会话中总有一个前台进程组(前台任务),可以从终端读取输入,向终端发送输出。如果用户输入Ctrl+C或者Ctrl+Z,就可以分别让任务终止或挂起。同时,一个会话还可以拥有任意多个后台进程组,后台进程组可以用’&’结尾的命令行创建。
任务控制
支持任务控制的shell提供了创建后台任务、列出所有任务、向任务发送信号,以及在前后台任务之间来回切换等命令。
shell中的任务分为三种状态Running、Stopped、Done。
1 | <command> & |
在一个命令后添加 & 即可简单的放入后台运行。通过 & 放置到后台的命令,仍保持 Running 状态,默认的标准输出和标准错误输出仍为终端,也就是说你仍然会看到它打印出的信息,这应该通过重定向来解决。如果输出的内容不需要,可以简单的重定向到 /dev/null。
当与终端断开连接时(即关闭终端),任务会收到 SIGHUP 信号而被杀死,如果需要持续运行,则需使用 nohup 命令将其放置到系统后台,而非当前终端的后台,如:
1 | $ nohup python3 local.py 2>&1 & |
这将放入系统后台运行python3 local.py
,并将 stderr 重定向到 stdout。这是我们在终端中输入exit
来退出终端,该任务就不会被杀死。
1 | CTRL+Z |
这将暂停当前任务,成为 Stopped 状态,并放入任务列表。
1 | jobs |
显示所有当前任务,如:
1 | $ jobs |
1 | fg |
通过fg [%n]
来激活任务到前台,如果省略%n
参数,则默认激活标记为+
的任务,且标记为-
的任务将被标记为+
。
1 | bg |
通过bg [%n]
来运行Stopped状态的后台任务,任务将继续运行,状态变为Running,且命令后增添了 & 字样。
当你忘记将任务放入后台运行,即可组合使用 CTRL+Z 和 bg 来弥补它。
1 | kill |
通过 kill –signal %n 来快捷地杀死后台任务。
signal 常见的有:
1 | 1 SIGHUP 终端断开连接 |