如何通过ssh或telnet将终端大小更改发送到命令行应用程序?

fad*_*bee 7 linux vim ssh terminal telnet

如何通过ssh或telnet将终端大小更改发送到命令行应用程序?

  1. 用户使用ssh或telnet连接到远程计算机.

  2. 他们开始在VIM中编辑文档.

  3. 然后他们调整终端窗口的大小.

终端必须告诉ssh/telnet窗口大小已经改变.这是怎么发生的?

然后ssh/telnet使用它自己的特定方法将该更改发送到sshd/telnetd.这些方法是什么?

然后sshd/telnetd告诉应用程序终端大小已经改变.怎么做 它是从终端到ssh/telnet的方法吗?

cni*_*tar 11

这是伪终端的凌乱世界.

在本地,当您调整终端的大小时,前台进程组会获得一个SIGWINCH,您可以使用它ioctl来获取新的大小.但是这与远程 vim进程有什么关系呢?

主题非常复杂,但它的要点是删除服务器(sshd)执行此操作:

  1. 使用posix_openpt(或openpty)打开主psedoterminal设备
  2. 分叉一个新的孩子(通常这必然会变成一个shell)
  3. 使用断开其终端连接 setsid()
  4. 打开终端设备(在步骤1中创建),该终端设备成为其控制终端
  5. STDIN_FILENO用步骤4中的fd 替换标准描述符(和朋友)

此时,服务器进程写入主端的任何内容最终都作为输入到从属端BUT 并具有终端线规则,因此内核在编写某些组合时会发出一些魔术 - 比如发送信号 - 并且您还可以发出ioctl呼叫有用的效果.


考虑这一点的最佳方式是探索openssh套件.

  • 客户端监视SIGWINCH- 查看clientloop.c并设置received_window_change_signal = 1何时收到它

  • 该函数client_check_window_change检查该标志并告诉服务器:

    packet_start(SSH_CMSG_WINDOW_SIZE);
    packet_put_int((u_int)ws.ws_row);
    ...
    
    Run Code Online (Sandbox Code Playgroud)

所以现在服务器应该接收一个指定(可能是新的)大小的数据包.

  • 服务器pty_change_window_size使用收到的大小调用真正的魔法:

    struct winsize w;
    w.ws_row = row;
    ...
    (void) ioctl(ptyfd, TIOCSWINSZ, &w); /* This is it! */
    
    Run Code Online (Sandbox Code Playgroud)

这将设置从站的新窗口大小.如果新大小与旧大小不同,则内核将a发送SIGWINCH与该pty关联的前台进程组.因此vim也获得该信号并且可以更新其终端大小的想法.

  • @chrisdew 说实话,当你问我时,我知道主要思想但不知道细节,所以我想什么时候研究它更好。 (2认同)
  • 它对于 ssh 确实很有帮助,但是 telnet 呢? (2认同)