【get_pty】和【tty】理解
- get_pty参数
# pty(pseudo terminal device)由两部分构成,ptmx是master端,pts是slave端,
get_pty这个参数,实际在远程执行sudo命令时,一般主机都会需要通过tty才能执行,通过把get_pty值设置为True,可以模拟tty,
但是随之而来也会有一个问题,如果是远程执行一个需要长期运行的进程,例如启动nginx服务,当远程命令执行后SSH退出之后,此次运行的所有程序也会随之结束**,
所以在需要通过远程命令运行某些服务或程序时,是不能指定get_pty参数的;
**但同时,如果是普通用户远程登录,是没有权限执行service命令的。建议的一种方式是修改/etc/sudoers配置文件,注释掉Defaults requiretty这行。
- tty
# tty:teletypewriters,原来指的是电传打字机
# pty(pseudo terminal device)由两部分构成,ptmx是master端,pts是slave端
#先用tty命令看看当前bash关联到了哪个tty
dev@debian:~$ tty
/dev/pts/1
#看tty都被哪些进程打开了
dev@debian:~$ lsof /dev/pts/1
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 907 dev 0u CHR 136,1 0t0 4 /dev/pts/1
bash 907 dev 1u CHR 136,1 0t0 4 /dev/pts/1
bash 907 dev 2u CHR 136,1 0t0 4 /dev/pts/1
bash 907 dev 255u CHR 136,1 0t0 4 /dev/pts/1
lsof 1118 dev 0u CHR 136,1 0t0 4 /dev/pts/1
lsof 1118 dev 1u CHR 136,1 0t0 4 /dev/pts/1
lsof 1118 dev 2u CHR 136,1 0t0 4 /dev/pts/1
#往tty里面直接写数据跟写标准输出是一样的效果
dev@dev:~$ echo aaa > /dev/pts/2
aaa
# 通过上面的lsof可以看出,
当前运行的bash和lsof进程的stdin(0u)、stdout(1u)、stderr(2u)都绑定到了这个TTY上。
# 键盘显示器直连(终端)
+-----------------------------------------+
| Kernel |
| +--------+ | +----------------+
+----------+ | +-------------------+ | tty1 |<---------->| User processes |
| Keyboard |--------->| | +--------+ | +----------------+
+----------+ | | Terminal Emulator |<->| tty2 |<---------->| User processes |
| Monitor |<---------| | +--------+ | +----------------+
+----------+ | +-------------------+ | tty3 |<---------->| User processes |
| +--------+ | +----------------+
| |
+-----------------------------------------+
# SSH远程访问
+----------+ +------------+
| Keyboard |------>| |
+----------+ | Terminal |
| Monitor |<------| |
+----------+ +------------+
|
| ssh protocol
|
↓
+------------+
| |
| ssh server |--------------------------+
| | fork |
+------------+ |
| ↑ |
| | |
write | | read |
| | |
+-----|---|-------------------+ |
| | | | ↓
| ↓ | +-------+ | +-------+
| +--------+ | pts/0 |<---------->| shell |
| | | +-------+ | +-------+
| | ptmx |<->| pts/1 |<---------->| shell |
| | | +-------+ | +-------+
| +--------+ | pts/2 |<---------->| shell |
| +-------+ | +-------+
| Kernel |
+-----------------------------+
#这里可以看到sshd已经打开了/dev/ptmx
dev@debian:~$ sudo lsof /dev/ptmx
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sshd 1191 dev 8u CHR 5,2 0t0 6531 /dev/ptmx
sshd 1191 dev 10u CHR 5,2 0t0 6531 /dev/ptmx
sshd 1191 dev 11u CHR 5,2 0t0 6531 /dev/ptmx
收发消息
1.Terminal收到键盘的输入,Terminal通过ssh协议将数据发往sshd
2.sshd收到客户端的数据后,根据它自己管理的session,找到该客户端对应的关联到ptmx上的fd(file descriptor)
3.往找到的fd上写入客户端发过来的数据
4.ptmx收到数据后,根据fd找到对应的pts(该对应关系由ptmx自动维护),将数据包转发给对应的pts
5.pts收到数据包后,检查绑定到自己上面的当前前端进程组,将数据包发给该进程组的leader
6.由于pts上只有shell,所以shell的read函数就收到了该数据包
7.shell对收到的数据包进行处理,然后输出处理结果(也可能没有输出)
8.shell通过write函数将结果写入pts
9.pts将结果转发给ptmx
10.ptmx根据pts找到对应的fd,往该fd写入结果
11.sshd收到该fd的结果后,找到对应的session,然后将结果发给对应的客户端
#####
#TTY和PTS的区别
从上面的流程中应该可以看出来了,对用户空间的程序来说,他们没有区别,都是一样的;
从内核里面来看,pts的另一端连接的是ptmx,而tty的另一端连接的是内核的终端模拟器,ptmx和终端模拟器都只是负责维护会话和转发数据包;
再看看ptmx和内核终端模拟器的另一端,ptmx的另一端连接的是用户空间的应用程序,如sshd、tmux等,而内核终端模拟器的另一端连接的是具体的硬件,如键盘和显示器。
常见的TTY配置
https://segmentfault.com/a/1190000009082089
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· Qt个人项目总结 —— MySQL数据库查询与断言