SSH、SHELL和终端(一)

2,931 阅读5分钟

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战」。

SSH是怎么工作的

本文从实际案例出发,梳理ssh相关的细节和原理。

ssh连接

作为程序员,我们每天都会执行很多次的一个非常简单的操作就是远程连接服务器。

在笔记本或PC上打开终端,敲入 ssh root@server,这样就ssh到某台服务器上了。

MB1$ ssh root@server

~# ps $$
PID TTY STAT TIME COMMAND
28348 pts/0 Ss 0:00 -bash

~# ps -ef |grep 28348
root 988 28348 0 22:26 pts/0 00:00:00 ps -ef
root 989 28348 0 22:26 pts/0 00:00:00 grep --color=auto 28348
root 28348 28346 0 21:53 pts/0 00:00:00 -bash

 ~# ps -ef |grep 28346
root 28346 9709 0 21:53 ? 00:00:00 sshd: root@pts/0
root 28348 28346 0 21:53 pts/0 00:00:00 -bash

从上面几个命令可以看出,客户端远程连接上服务器之后:

  • ps $$打印当前终端的bash进程信息,Time 0:00表示刚连上去,Stat Ss 表示是一个前台程序,S表示处于sleep状态,s表示有子进程
  • 当前bash进程的PID是 28348
  • ps -ef |grep 28348显示28348的子进程有ps -ef和grep --color=auto 28348,父进程的PID是28346
  • 查看bash进程的父进程信息,它是sshd: root@pts/0 如下图:

ssh4.png

可以看出,客户端连接ssh服务器后,ssh服务器产生了一个bash进程,这个bash进程的tty是pts/0。

pts/0是sshd软件模拟的一个虚拟tty,一个虚拟的显示器概念。下面还有tty的介绍。

连接建立过程

  • 建立tcp连接,ssh和sshd程序通过socket建立连接通道
  • sshd产生一个虚拟终端和子进程bash
  • ssh模拟在客户端终端上服务端的输入输出

通信流程

  • 客户端在ssh程序的输入发往服务端sshd
  • 服务端sshd将客户端的命令输入虚拟终端pts/0
  • bash进程的标准输入是pts/0,则bash得到输入,开始干活
  • bash进程根据输入的shell命令产生新的子进程,如果是前台进程,则阻塞等待子进程完成
  • 子进程继承了父进程的标准输入输出,打印信息输出到终端

厘清概念

通过上面的流程分析已经有了基本的概念,但是发现这个简单案例的信息量却很大,是因为有很多概念和名词需要梳理清楚。虽然在实际学习和工作中,我们可能不会去注意或总是搞混这些概念。

shell和bash

shell是操作系统外包裹的壳,shell其实就是用户与linux系统沟通的一个桥梁。

ssh2.png

可以认为shell是一个接口,bash是shell的一种实现,shell的实现还有sh,zsh等。 我们可以在系统里面运行多个bash进程

终端、控制台和Console

这三个词都是一样的,都是指终端。

关于tty

  • tty的电传打字机的简称,因为最早使用的输入输出就是电传打字机。后来被视频显示终端所替代。

ssh3.png

  • pts是sshd进程远程连接产生的,是一个终端模拟器

标准输入输出和终端

在linux操作系统中,外部设备用什么表示?是用文件。linux中一切设备皆是文件!

  • 系统的文件抽象用 文件描述符表示
  • SHELL程序会使用0、1、2这三个文件描述符,0号fd表示进程的标准输入,1号fd表示进程的标准输出,2表示标准错误
  • bash进程的标准输入是终端,标准输出也是终端,标准错误也是终端。

终端和进程

从终端开始运行的进程都会依附于这个终端,这个终端称为这些进程的控制终端,也就是图上的tty。 在一个终端上运行的程序可以分为前端进程和后端进程。

  • 前端程序的标准输入也是终端,会阻塞bash进程。
  • 后端程序的标准输入不从终端读取,则不会阻塞bash进程。

如果终端关闭了,则会发HUP信号给这个终端的前后端进程。HUP信号是终端被中止的时候向它所关联的进程所发出的信号,进程收到这个信号后就会中止运行。

所以这样就能理解为啥终端关闭,和终端相关的进程就关闭了。

  • bash是第一个依附于这个终端的前端程序,终端关闭则bash进程关闭
  • &启动的是后台进程,但在终端关闭的时候,这些后台线程也会收到HUP信息
  • nohup启动的后台线程会忽略终端关闭发起的HUP信息。所以如果你不希望进程被这个信号干掉的话,就可以忽略这个信号。

Session会话

上面讲的控制终端其实控制的是会话(Session)。

  • session是和shell关联的,每打开一个shell的进程,就会创建一个新的session。

ssh5.png

  • 每一次登录都会产生一个会话,可以是远程登录也可以是本地登录
  • 会话需要有系统认可的身份登录,在session里面可以切换用户
  • bash进程是这个Session的第一个进程,
  • SID和bash进程的PID一样
  • 进程会被标记上SessionID,也就是SID

结语

本文只讲了一个简单的案例并梳理这个案例里面的概念,下一篇会进一步分析shell、终端相关的原理和应用。