Published
-
All about Terminal, Session and Process Group
常常能注意到一件事情:比如说当我打开两个终端窗口时
- 按两次cmd+w,会关闭两个窗口,但是终端进程没有终止
- 按一次cmd+q,会直接关闭所有窗口,终端进程终止
- 实际上,这是因为系统的终端程序(准确说是一个终端模拟器)并非前台所直接呈现给你的shell窗口。终端程序通过fork和exec启动shell进程,这个shell进程被设置为终端的子进程。关闭终端程序(cmd+q),自然就会关闭所有子进程啦!
基本定义
- session(会话期):一个或多个进程组的集合,有唯一一个会话期首进程(session leader). 会话期ID为首进程的ID.
- process group(进程组):一个或多个进程的集合,每一个进程组有唯一一个进程组ID,即进程组长进程的ID.
控制终端是与会话关联的一个终端设备。一个会话期只会对应一个终端,该终端负责与前台进程组进行交互。
命令行操作是谁发出的?
当你在终端中输入命令时:
-
键盘输入流程:
- 你的按键输入首先被终端软件捕获
- 终端将这些按键发送到伪终端的主设备端
- 内核将输入传递到伪终端的从设备端
- Shell从从设备端读取这些输入
-
命令执行流程:
- Shell负责解析和执行命令,而不是终端
- 当你按下Enter键,Shell解析整行输入
- Shell决定如何执行命令(内置命令、外部程序等)
- 如果需要执行外部程序,Shell会fork并exec新进程
-
输出显示流程:
- 命令的输出写入到标准输出(连接到伪终端的从设备端)
- 内核将输出传递到伪终端的主设备端
- 终端程序从主设备端读取输出并在窗口中显示
具体示例
当你在终端中输入ls -l并按Enter:
- 终端软件捕获你的按键并传递给bash
- bash接收完整命令行后解析它
- bash确定需要执行外部程序
ls - bash创建子进程并在其中执行
ls程序 ls程序生成目录列表并写入标准输出- 输出通过伪终端传递给终端软件
- 终端软件在窗口中显示输出
当你通过ssh与远程服务器建立连接:

控制终端关闭: SSH会话创建了一个伪终端(PTY),作为远程shell的控制终端:
- 终端关闭:
- 当SSH连接断开时,伪终端的主设备端关闭
- 这导致从设备端也关闭
- 终端关闭信号:
- 当控制终端关闭时,内核会向与该终端关联的会话中的前台进程组发送SIGHUP信号
- 这是独立于sshd进程终止发送的SIGHUP的另一个信号源
如何解决?
-
使用screen/tmux!
- 之后新创建的进程都是screen的子进程,而screen已经从终端上分离,不会因为终端关闭而终止。
-
screen使用方法:
- 创建新会话:
screen - 分离会话:
Ctrl+a d - 重新连接:
screen -r <session_name> - 列出所有会话:
screen -ls - 杀死会话:
screen -X -S <session_name> quit - 异常attach,需要踢掉原有用户:
screen -D -r <session_name>
- 创建新会话: