可调整大小的串行控制台窗口?


25

使用系统的串行控制台时,我总是以$COLUMNS=80和结尾$LINES=24

尽管我可以手动更改这些变量,但是在客户端终端窗口调整大小后,每次执行此操作都会有些烦人。

通常,我使用来连接到控制台screen /dev/mytty baudrate

$TERM环境变量更改为“ screen”或“ xterm”无济于事。

我需要打电话给getty其中一些而不是vt100吗?

不用说,当我使用ssh连接到同一台计算机时,所有这些工作正常。

Answers:


26

就像我前面提到的注释程序一样,resize在每个命令之后都没有替代方法,如果您没有此命令,并且不想在(xterm)中安装软件包,这里有两个POSIX shell脚本,它们执行相同的操作使用ANSI终端转义码:

res() {

  old=$(stty -g)
  stty raw -echo min 0 time 5

  printf '\0337\033[r\033[999;999H\033[6n\0338' > /dev/tty
  IFS='[;R' read -r _ rows cols _ < /dev/tty

  stty "$old"

  # echo "cols:$cols"
  # echo "rows:$rows"
  stty cols "$cols" rows "$rows"
}

res2() {

  old=$(stty -g)
  stty raw -echo min 0 time 5

  printf '\033[18t' > /dev/tty
  IFS=';t' read -r _ rows cols _ < /dev/tty

  stty "$old"

  # echo "cols:$cols"
  # echo "rows:$rows"
  stty cols "$cols" rows "$rows"
}

顺便说一句,在我的.profile文件中,您将找到以下内容: [ $(tty) = /dev/ttyS0 ] && res 这样,在每次通过串行线路登录时(我用于管理的登录),例如在重启设备后,就可以确定终端的大小。
另请参见rsaw在注释中的想法,使该行[ $(tty) = /dev/ttyS0 ] && trap res2 DEBUG出现在该行中,以便在每个命令后都执行调整大小操作(请注意,busybox虽然AFAIK并非总是如此,但并非总是如此)。


3
PS:要使其更永久,请添加[[ $(tty) == /dev/ttyS0 ]] && trap res2 DEBUG到外壳程序配置文件配置之一(例如/etc/profile~/.bash_profile)。这将使其在每个命令之后运行(仅当您使用screen / tmux / terminal-emulator调整窗口/窗格的大小时,这才是一件好事)。
rsaw

2
使用它的几个分钟后,我很快就意识到,这两个resres2太慢任何东西,但使用在第一次登录。在我的机器上,它们都需要0.5秒才能完成...使我的所有命令显得缓慢(当与DEBUG陷阱一起使用时)。哎呀!不能那样 猜猜我要安装xterm
rsaw 2016年

3
@phk xterm的resize速度更快-通常为0.002秒。
rsaw '16

1
@rsaw哦,好的,很高兴知道,我认为它的行为类似,因此也同样慢。我记得在某些情况下,这busybox对我来说似乎同样缓慢。
phk

1
感谢您的独立解决方案。我正在使用未安装x11或xterm的仅控制台发行版,因此resize不是一种选择。
thom_nic

16

仅作记录,这是此问题的答案(Usenet赢了):

在调整大小操作之后xtermrxvt将接收SIGWINCH在虚拟终端应用程序(和)中运行的控制台应用程序。因此,应用程序将能够在相应的信号处理程序中重绘窗口等。

不幸的是,使用串行控制台时,没有这种机制。

但是,应用程序可能会主动要求当前控制台窗口的大小。因此,第二件事是每当外壳程序打印命令提示符时都执行此操作。

这可以通过首先编译一个特殊的调整大小的可执行文件,然后在以下代码中使用以下代码来实现bashrc

if [ $(tty) == '/dev/ttyS0' ]; then
  trap resize DEBUG
fi

当然,这不会在运行时更改控制台应用程序中的控制台大小设置。


1
它不应该是可能的运行串行线路的协议,即提供所有的功能?我的意思是我们确实有一个客户端和一个服务器。他们可以使用带内转义序列来执行几乎所有操作,并且仍然可以与纯文本串行控制台一起使用!
Evi1M4chine '16

1
实际上,代码中的注释清楚地表明它不是resize您系统上安装的版本。
Thomas Dickey

9

这样的“可调整大小”终端是NAWS的结果(Negotiate About Window Size来自RFC 1073 Telnet窗口大小选项)。

如果您使用串行端口直接连接到计算机,则不涉及协商,并且计算机不直接了解终端的屏幕尺寸。

如果终端可以协商大小,则计算机将发送SIGWINCH到终端中运行的应用程序,告诉他们更新其屏幕大小的概念。

当计算机不知道屏幕大小时,通常会将stty -a(行和列)显示的大小设置为零。对于交互使用,这是一个有点不友好,和一些系统使用环境变量LINESCOLUMNS提供帮助。所分配的值可以从终端描述中得出。通常,它们只是硬编码。这些变量的约定要求它们生效,除非明确禁止(例如在curses应用程序中use_env起作用)。从积极的方面来说,如果没有可靠的信息,这些变量可能会很有用。不利的一面是,没有方便的方法来更改这些变量。

resize程序(随附带的实用程序xterm)可以使用VT100样式的光标位置报告转义序列来确定屏幕尺寸。可以从命令行运行。再也没有自动执行此操作的便捷方法。副作用是,resize更新了所看到的行/列上的信息stty。它提供更新的环境变量的用途是这样的情况下,其中主要是有用的LINESCOLUMNS 设定的,应该进行更新。


3

这是另一个对我的嵌入式Linux系统(运行Angstrom的Overo)非常有用的解决方案。我只是从我的.bashrc文件中运行了它。我不想使用调整大小,因为这需要安装一些X软件包,而我则不需要。

告诉您的Raspberry Pi您的终端大于24行| 浅思博客


3
请不要仅仅发布一个链接:包括相关的详细信息,以便在此处也可以使用此信息...
jasonwryan 2014年

1
太糟糕了,它需要Python。
2014年


1

通过串行线路运行Shell会话时,resize在该会话内调用命令就足够了-在建立连接之后以及每次更改终端几何形状之后。

resize命令是xterm的一部分,但不依赖于X11。例如,在Fedora上,它分别打包为xterm-resize

工作原理:resize命令通过一些光标移动来测量高度/宽度,然后通过转义序列将这些值发送到终端。

使用像zsh这样的shell,它也可以自动更新LINESCOLUMNS变量(或者,可以评估命令打印到stdout的导出语句)。

为何需要这样做:通过本地或ssh会话,终端可以向会话发出有关几何变化的信号(请参见SIGWINCH)。该机制不适用于串行连接。


0

这是简单快速的调整大小功能,仅适用于bash。它是从phk的res2修改而来的,它使用bash read -d delim来避免让超时完成读取。

resize() {
  old=$(stty -g)
  stty -echo
  printf '\033[18t'
  IFS=';' read -d t _ rows cols _
  stty "$old"
  stty cols "$cols" rows "$rows"
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.