【问题标题】:How do I "dump" the contents of an X terminal programmatically a la /dev/vcs{,a} in the Linux console?如何在 Linux 控制台中以编程方式将 X 终端的内容“转储”为 la /dev/vcs{,a}?
【发布时间】:2014-07-14 06:34:31
【问题描述】:

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

重申和澄清,/dev/vcs{,a}* 是字符设备,用于检索内核控制台 VT100 仿真器的当前内存表示,表示为单个“行”文本(每个“行”)。
为了消除混淆,我想指出我不能tail -f 这个设备:它不是像 TTY 本身那样的字符流。 (但我从来不需要这种行为,因为它值得。)

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

我想说的是,我确实理解并意识到 tty 本身并不是一个“屏幕缓冲区”,而是一个字符流,并且我在上面基本上利用的非标准功能是 Linux VT102 特有的一种古怪功能模拟器。然而,这个功能已经足够酷了(为什么它会在主线树中?:D),在我看来,有 应该与 /dev/pts* 一起工作的东西与之对应。

今天下午,我需要对交互式 ncurses 应用程序的输出进行屏幕抓取,以便从终端中显示的信息中提取元数据。 (没有其他实用的方法可以实现我的目标。)Linux 的内核 VT100 驱动程序可以轻松完成这样的任务非常,我做了错误地认为,鉴于此,在 X11 下做同样的事情不可能真的那么难。

到上午 9 点,我决定尝试性地请求远程屏幕转储的最简单方法是在 dtach 中运行它(认为“screen -x”没有任何其他选项)并破解 dtach请求屏幕更新并退出的代码。

大约上午 11 点到下午 12 点,我请求更新屏幕并将其转储到 stdout

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

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

我之前检查过screen,发现代码足够疯狂,足以消除我可能不得不破解它的任何倾向;我只能说,这种精神错乱可能是screen 还没有我在这里介绍的功能的原因之一(可以说这很容易实现)。

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

【问题讨论】:

    标签: linux terminal console screen-scraping gnu-screen


    【解决方案1】:

    我没有将其标记为已接受,因为它不能解决实际的核心问题(这是多年前的问题),但我能够实现我设定的具体目标。

    我的具体要求是我想截取ncdu 交互式磁盘使用浏览器的输出,所以我可以简单地在另一个终端中按 Enter(或执行一些类似的简单序列)来添加当前突出显示的目录/在ncdu 中选择到我想要使用的文件的文件列表。
    我的目标是不必用无休止的复制+粘贴和/或重新输入目录名称来分散自己的注意力(可能有不少不准确的地方)启动),所以我可以专注于我想要选择的目录。

    screen 具有刷新功能,可通过按(默认)CTRL+A, CTRL+L 访问。我扩展了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 窗口(我使用焦点跟随鼠标),然后按 Enter。这会将文件添加到列表中(一个简单的文本文件本身)。

    话虽如此,我想澄清一下,上面的正则表达式不是可以运行的代码示例;相反,它是一个警告:对于超出令人难以置信的琐碎 (!!) 内容提取(例如此处介绍的内容),您基本上进入了与想要从基于 VT100 的系统转换为更现代的系统的大型公司/利益集团,他们不得不花费数以千计的费用来调试大型翻译框架,以特别大规模地执行上述类型的转换。

    更明智的解决方案值得赞赏。

    【讨论】:

      猜你喜欢
      • 2013-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-09
      • 1970-01-01
      • 2011-06-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多