诸如 top 之类的命令如何更新输出而不在控制台中附加内容?

诸如 top 之类的命令如何更新输出而不在控制台中附加内容?

我通过 PuTTY 终端仿真器使用 SSH 连接到远程 Linux 服务器。我注意到我运行的命令和控制台上的输出不断附加在终端窗口中。我的意思是,当我使用滚动条并上下滚动时,我可以看到我之前运行的命令及其输出,就像在打印纸上一样。但是,有些命令会top不断更新输出,而不会在控制台上附加显示。它是如何工作的?

答案1

这里可能有两种机制在起作用。

一种是使用 ANSI 转义码(在某些情况下还有其他非 ANSI 代码),正如 Martin Prikryl 在他们的回答中所提到的,实现基于文本的伪图形界面。这个最低限度恰好是两个特定的 ANSI 转义码,,^[[2J它会清除屏幕上的所有内容,和^[[;H,它会将光标移动到屏幕的左上角。通过组合它们,您可以逐个写出每个“帧”的内容,而无需添加到回滚缓冲区。大多数应用程序实际上使用的远不止这些(例如,有一组用于将光标移动到任意方向的代码,使用这些代码跳过屏幕上应该“空”的部分是很正常的)。实际上,大多数(但绝不是全部)大型应用程序都使用 libcurses(或更常见的是 ncurses)或直接等效程序来为它们处理所有这些。

另一种可能性通常与使用 ANSI 转义码结合使用来操作屏幕内容,这是最初由 xterm 提供的特殊功能,但现在已被大多数不错的终端仿真器广泛实现。有一对转义码(^[[?1049h^[[1049l)用于在此和常规回滚缓冲区之间切换。通过在呈现文本 UI 之前切换到备用屏幕缓冲区,程序可以完全避免改变回滚缓冲区,这不仅可以防止您在没有拦截通常会滚动的击键的情况下滚动,还允许程序执行诸如让您检查程序运行之前的现有终端内容(并使您更容易看到在打开全屏应用程序之前您正在做什么)之类的操作。

答案2

您所观察到的是历史发展的产物。

最早的交互式终端是真正的电传打字机;本质上是连接到电话线的电动打字机。(有没有想过为什么 /dev/终端是以何种方式命名的?您可以键入一个文本命令(如果我没记错的话,甚至包括一些基本的、笨拙的行编辑)并获得文本输出。

当然,它们只能从左到右和从上到下移动。哦,等等,不对!他们可以用 Ctrl-H 返回一个字符并再次输入,使其变为粗体。看,这就是有些程序仍然为打印机格式化文本。电传打字机也有一些基本的控制代码,如换行、换页或铃声。

转向基于 CRT 的终端是合乎逻辑的,即使只是为了保护树木。但从那时起,每个终端(仿真器)都提供了电传打字机的基本功能:除非另有说明(使用著名的转义序列),否则接收到的 7 位 ASCII 代码(包括基本控制代码)将被解释为相应的字符或命令,并从左到右、从上到下显示,从终端维护的当前光标位置开始。

但是,由于更智能的终端实际上​​能够在屏幕上的任意行/列位置显示字符,因此它们都可以通过控制代码序列以编程方式执行此操作,并且操作系统以某种方式配置为使用适当的序列。一些程序,特别是编辑器、shell 和其他交互式、面向用户的程序(如 top)使用此功能来控制整个屏幕。

这种“可视化模式”并不常见的原因是,仅输出不带“修饰”的线性字符序列就非常灵活 — 同时足以满足各种输出需求:您可以打印制表数据,该数据本质上仍然是带有空格(空格、制表符、换行符)的连续字符序列。整个 Unix/Linux 生态系统(包括管道和设备)都是围绕此范例构建的。它允许您将 find、grep、cut 等“构建块”插入在一起并自动处理文本信息。如果输出与定位和格式化命令混合在一起,那将完全不可能。

答案3

大多数命令只是将行打印到终端。终端客户端只是像古老的行打印机一样打印这些行。回滚是无尽的纸从打印机中出来。

但终端客户端(又名终端仿真器) 可以做更多的事情,包括在屏幕上移动光标,从而允许服务器(远程应用程序)在“终端屏幕”的任意点上打印。这就是诸如top、、viMidnight Commander 等应用程序所利用的,以实现全屏“GUI”界面(实际上是TUI 界面)。这些高级功能是使用ANSI 转义代码

相关内容