ssh 如何始终设法重置终端属性?

ssh 如何始终设法重置终端属性?

如果我跑

strace -e trace=ioctl -v ssh some_remote_host

我看到这样一行:

ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {c_iflags=0x6006, c_oflags=0x4, c_cflags=0x
4bf, c_lflags=0xa00, c_line=0, c_cc[VMIN]=1, c_cc[VTIME]=0, c_cc="\x03\x1c\x7f\x
15\x04\x00\x01\xff\x11\x13\x1a\xff\x12\x0f\x17\x16\xff\x00\x00"}) = 0

这是有道理的:ssh必须更改很多终端设置,例如:

  • 它会关闭,ISIG因为 ^C 和 ^Z 应该中断并挂起远程主机上的进程,而不是ssh本地运行的进程;
  • 它关闭了ICANON因为它想要接收无缓冲的键盘输入而不是行缓冲;
  • 它会关闭,ECHO因为是否发生回显应取决于远程主机伪终端上设置的属性,而不是在本地终端上自动发生

如果您现在退出ssh会话,则通过第二次调用恢复原始终端属性ioctl

ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {c_iflags=0x6d02, c_oflags=0x5, c_cflags=0x
4bf, c_lflags=0x8a3b, c_line=0, c_cc="\x03\x1c\x7f\x15\x04\x00\x01\xff\x11\x13\x
1a\xff\x12\x0f\x17\x16\xff\x00\x00"}) = 0

但我觉得奇怪的是,即使之前ssh被杀了SIGKILL它也有机会做出第二个ioctl,你也会恢复原来的终端属性。否则你会注意到有些事情是非常错误的(例如在 shell 中输入的命令会不是予以回应)。ssh即使不再呼叫,如何保证恢复原来的终端属性ioctl

答案1

shell 知道终端ssh已死并且可以重置终端。

当我杀死一个孩子时跟踪 bash shellssh表明它进行了多次 ioctl() 调用。

--- SIGCHLD (Child exited) @ 0 (0) ---
ioctl(255, TIOCSPGRP, [52631])          = 0
ioctl(0, TIOCGWINSZ, {ws_row=25, ws_col=147, ws_xpixel=902, ws_ypixel=329}) = 0
ioctl(0, TIOCSWINSZ, {ws_row=25, ws_col=147, ws_xpixel=902, ws_ypixel=329}) = 0
ioctl(0, SNDCTL_TMR_TIMEBASE or TCGETS, {c_iflags=0x500, c_oflags=0x5, c_cflags=0xbf, c_lflags=0x8a3b, c_line=0, c_cc="\x03\x1c\x7f\x15\x04\x00\x01\x00\x11\x13\x1a\x00\x12\x0f\x17\x16\x00\x00\x00"}) = 0
ioctl(0, SNDCTL_TMR_STOP or TCSETSW, {c_iflags=0x400, c_oflags=0x5, c_cflags=0xbf, c_lflags=0x8a31, c_line=0, c_cc[VMIN]=1, c_cc[VTIME]=0, c_cc="\x03\x1c\x7f\x15\x04\x00\x01\x00\x11\x13\x1a\x00\x12\x0f\x17\x00\x00\x00\x00"}) = 0

相关内容