Linux的内核级控制台/非X终端仿真器包含一个非常酷的功能(如果在其中编译):每个/dev/ttyN设备与/dev/vcsaN/dev/vcsN设备相对应,它们表示该tty的内存(显示)状态,带有和不带有属性(颜色,闪烁等)。这使您可以非常轻松地生成cat /dev/vcs7,并在启动/dev/tty7的任何位置查看cat的转储。前几天,我使用了这一难以置信的实用功能,通过SSH登录到系统,并远程观看了我忘记放入dd(或类似 session ) session 的screen进程-该进程在文本控制台上运行,因此我花了一些时间调整我想要抓取的字符范围的时间,目前我正在通过SSH观看dd的传输状态(偶然,每秒一次)。

为了重申和阐明,/dev/vcs{,a}*是字符设备,用于检索内核控制台VT100仿真器的当前内存表示形式,表示为文本的单个“行”(屏幕的每个“行”的末尾都没有“换行”。 )。为了消除困惑,我想指出我不能tail -f这个设备:它不是TTY本身的字符流。 (但是我从来不需要这种行为,因为它值得)。

我一直为寻求一种方法来转储X终端仿真器的字符单元存储器状态(或者实际上需要与ttys配合使用的任意进程)的方式而困扰了多年,这与我在Linux控制台中使用的方式类似。而且...令我感到惊讶的是,对于这个问题没有实际的解决方案-因为它已经存在了大约30年-1984年引入了X-或被脚的是至少19年-引入了/dev/vcs{,a}*在内核1.1.94中;该版本中的最新文件日期为1995年2月22日。(最旧的日期为1993年12月1日:P)

我想说的是,我确实理解并认识到tty本身并不是一个“屏幕缓冲区”,而是一个字符流,并且我上面本质上利用的非标准功能是特定于Linux VT102仿真器的古怪功能。但是,此功能非常酷(为什么在主线树中还会显示呢?:D ),我认为应该与相对,以便与/dev/pts*一起使用。

今天下午,我需要在屏幕上抓取交互式ncurses应用程序的输出,以便可以从终端中显示的信息中提取元数据。 (没有其他实用的方法可以达到我想要的目标。)Linux的内核VT100驱动程序可以轻松完成这样的任务,因此我犯了一个错误,认为它是,在X11下做同样的事情并不难。

到了9AM,我决定实验性地请求转储远程屏幕的最简单方法是在 dtach 中运行它(认为“screen -x”而不使用任何其他选项),然后破解dtach代码以请求屏幕更新并退出。

在11 AM-12PM左右,我正在请求屏幕更新并将其转储到stdout

下午3:30左右,我接受了使用dtach是不可能的:

  • 首先,根据设计,它依赖于应用程序本身根据请求发送屏幕重绘,以保持代码简单。太好了,但是,幸运的是,我使用的应用程序不支持全屏重绘-它只会在屏幕尺寸变化时重新绘制(并且仅在屏幕尺寸确实不同的情况下!)。
  • screen session 中运行程序(因为screen是真正的终端模拟器,并且具有内部2D字符单元缓冲区),然后在screen -x内运行dtach,也神秘地无法生成字符单元更新。

  • 我以前检查过screen,发现该代码足够疯狂,可以消除我可能不得不改写的任何倾向。我只能说,疯狂可能是screen不具备我在此处介绍的功能的原因之一(可以说很容易实现)。

    与此类似的其他问题也经常得到使用typescript或script的答案;我只想澄清一下script将tty本身的流保存到文件中,我需要通过VT100仿真器来获得有关该tty当前状态的屏幕图像。换句话说,script对我的问题将是一个非常疯狂的解决方案。

    最佳答案

    我没有将其标记为可以接受,因为它不能解决实际的核心问题(已有多年历史了),但是我能够实现我设定的特定目标。

    我的特定要求是我想对 ncdu 交互式磁盘使用情况浏览器的输出进行屏幕抓取,因此我可以简单地在另一个终端中按Enter键(或执行一些类似的简单步骤),将ncdu中当前突出显示/选择的目录添加到我想使用的文件的文件列表。我的目标不是要无休止地复制目录和粘贴和/或重新键入目录名称(可能没有一些启动错误),所以我可以专注于我要选择的目录。
    screen具有刷新功能,可通过按(默认)CTRL + A,CTRL + L来访问。除了将远程屏幕转储到stdout之外,我还扩展了dtach的副本,使其能够发送击键,并将dtach包装在一个脚本中,该脚本将刷新序列(\001\014)传输到screen -x内部运行的dtach。这完美地工作了,可以检索完整的屏幕更新而没有任何闪烁。

    我会警告任何有兴趣尝试此技术的人,您将需要完善躲避VT100转义序列的技巧。我为此使用了正则表达式,所以我没有编写数千行代码。这是脚本的特定部分,它提取了我需要的两条信息:
    sh -c "(sleep 0.1; dtach -k qq $'\001\014') &"; path="$(dtach -d qq -t 130000 | sed -n $'/^\033\[7m.*\/\.\./q;/---.*$/{s/.*--- //;s/ -\+.*//;h};/^\033\[7m/{s/.\033.*//g;s/\r.*//g;s/ *$//g;s/^\033\[7m *[^ ]\+ \[[# ]*\] *\(\/*\)\(.*\)$/\/\\2\\1/;p;g;p;q}' | sed 'N;s/\(.*\)\n\(.*\)/\2\1/')"
    由于屏幕截图很酷,可以帮助人们可视化事物,因此下面来看它在运行时的工作方式:

    ncdu-scrape窗口底部显示的文件倒置是从ncdu窗口本身进行屏幕抓取的;列表中有四个文件,因为我使用ncdu中的箭头键选择了它们,将鼠标移到ncdu-scrape窗口(我使用focus-follows-mouse),然后按Enter。这会将文件添加到列表中(一个简单的文本文件本身)。

    说了这么多,我想澄清一下,上面的正则表达式不是要运行的代码示例;而是警告:对于超出琐碎(!!)内容提取之外的所有内容(例如此处提供的内容),您基本上会进入与想要从基于VT100的公司转换的大公司/利益集团相同的 Realm 系统到更现代的东西上去,这些人不得不花费成千上万的钱来调试大型翻译框架,这些框架会特别大规模地执行上述概述的转换。

    Saner解决方案受到赞赏。

    关于linux - 如何在Linux控制台中以编程方式在la终端/dev/vcs {,a}中 “dump”内容?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24730717/

    10-11 19:45
    查看更多