在 UNIX 和 Linux 系统上捕获屏幕快照和程序交互: 第 1 部分,程序交互

保存程序输出、提示、错误消息和用户输入

抓取屏幕快照、捕获程序和用户之间的交互是所有技术作者、大多数开发人员和很多技术营销人员都需要做的一件事情。现代 UNIX® 系统提供很多不同的工具来捕获用户和特定程序之间面向文本的交互,以及捕获图形屏幕和单个窗口。本文是三个部分的系列文章中的第 1 部分,主要关注各种不同的记录用户和命令行应用程序之间交互的方式。捕获用户输入和程序输出是有价值的,不仅用于内部或外部文档,也用于对很多应用程序开发人员来说常见的调试机制。

William von Hagen, 系统管理员,作家, WordSmiths

William von Hagen 担任 UNIX 系统管理员已经超过 20 年,并从 1993 年开始成为 Linux 爱好者。Bill 是一些图书的作者或合著者,涉及的主题包括 Ubuntu Linux、Xen Virtualization、GNU Compiler Collection (GCC)、SuSE Linux、Mac OS X、Linux 文件系统和 SGML。他还为 Linux 和 Mac OS X 出版物和网站撰写了许多文章。



2010 年 9 月 13 日

为什么要捕获命令行输入和输出?

很多命令行 UNIX 和 Linux® 命令的在线参考信息(手册页)是关于这些命令的信息的主要来源。所有手册页都被期望解释给定命令所有可用的选项,很多还提供与程序输出相关的例子,包括任何程序提示和相关用户输入。

要获得这样的信息,必须有人来创建这些例子。阅读源代码以查看所有可能的用户提示及其显示的内容,通常没有简单地运行程序看它做些什么来的直观。要将此体验转换成文档,开发人员(或者创建应用程序参考信息的作者)发现保存程序输入、提示和响应这些提示的用户输入的完整记录是非常有用的。

捕获用户与命令行应用程序的交互不只是一个写数据的任务。大多数命令行应用程序开发人员使用 C 编程语言的 printf() 命令(或者其他语言中的等价命令)作为他们的初始调试工具,即用它来显示整个应用程序中不同变量和数据结构的内容。根据显示信息的总量,通常最容易的方式是,将输出捕获到文件中,以备后续检查和分析。类似地,系统管理员通常喜欢保存交互式系统或服务器配置和初始化的逐步记录。

接下来几节探索各种捕获用户与命令行应用程序交互的方式,涉及到使用包含在所有 UNIX 和 Linux shell 中的特性,以及使用特定工具来自动化捕获这种类型的信息。

捕获输出和错误消息

UNIX 和 Linux 系统使得将程序输出和错误捕获在单独的文件中很容易,使用内置在这些系统上使用的命令解释器(叫做shell)中的功能即可做到。这些功能叫做 shell 重定向,允许用户通过使用尖括号字符或数字标识符,将程序输出(叫做 标准输出stdout)和程序错误输出(叫做 标准错误stderr)重定向到特定的文件或其他目的文件。不同的 shell 使用稍微不同的语法来捕获程序输出和错误消息,如下所示:

  • ls 程序的标准输出写到 /bin/sh、/bin/bash、/bin/csh 和 /bin/ksh shell 中的 file1 文件中:
    	ls > file1
  • ls 程序的错误输出写到 /bin/sh、/bin/bash、/bin/csh 和 /bin/ksh shell 中的 file1 文件中:
    	ls 2> file1

    (如果您使用的是 /bin/csh shell,没有容易的方式只把错误消息重定向到文件中。)

  • ls 程序的标准输出和错误输出都写到 /bin/sh、/bin/bash、/bin/csh 和 /bin/ksh shell 中的 file1 文件中:
    	ls &> file1
  • ls 程序的标准输出写到 file1 文件,将该程序的错误输出写到 /bin/sh、/bin/bash 和 /bin/ksh shell 中的 file2 文件中:
    	ls 1> file1 2> file2

Shell 重定向可以方便地将标准程序输出、程序错误消息或者这两者捕获到文本文件。但是如果您真正想要做的是捕获用户与程序的交互,那么这还不够。为此,您可以利用 shell 的 交互式功能和一种附加类型的输出重定向(叫做 管道)。

使用交互式 shell 捕获程序交互

前一节展示了如何将用户交互的特定方面写到特定的文件,如果您在试图捕获调试输出、程序使用信息等等,那么这是有帮助的。但是如果您在为应用程序编写文档,或者只是记录使用或试验某个应用程序,那么您想要看到您为程序提供的输入(标准输入stdin 的一个例子),以及应用程序对该输入的反应。本文最后两节讨论为此目的设计的一些应用程序。本节主要关注,只使用自己喜欢的 shell、一种附加类型的 shell 重定向(叫做管道)和一个标准的 UNIX 或 Linux 实用工具(叫做 tee),是如何捕获程序交互的。

在 UNIX 和 Linux shell 中,一个管道由 "|" 符号表示,将程序的标准输出连接到另一个程序的标准输入。如果您熟悉各种管道连接器,应该明白 UNIX 或 Linux tee 应用程序做它名字所隐含的事情 — 将输入分割成两个不同的流。其中一个流保持为标准输出,另一个流是一个文件,文件名由您在命令行指定。因此,您可以使用管道和 tee 命令的组合,将程序的输出重定向到文件中,并查看该输出。例如,下面这个命令既显示 ls /etc 命令的输出,又将该命令的标准输出捕获在 ls.out 文件中:

    ls /etc | tee ls.out

通过使用 "|&" 字符,您也可以在命令行用一个管道重定向标准错误和标准输出。例如,下面这个命令既显示 ls /etc 命令的输出和任何错误消息,又使用 tee 命令将输出和错误消息捕获在 ls.out 文件中:

    ls /etc |& tee ls.out

您可以使用下面这样的命令,通过一个管道、tee 命令和自己喜欢的 shell 的交互式模式组合标准输出和标准错误的重定向,以将所有输入、输出和错误消息捕获到一个文件中:

    bash -i |& tee output_file.txt

该命令以交互式模式执行 Bash shell,表示它本质上是一个您在显式终止它之前可以一直与之交互的 shell。该命令使用 "|&" 字符将该 shell 的所有输出和错误消息都重定向到 tee 命令,tee 命令既显示所有的输出和错误消息,又将所有内容的副本保存到 output_file.txt 文件。在执行您想要捕获与它的交互的任何命令时,可以键入 exit 命令(大多数系统上也可以按 Control-d 组合键)来终止 shell。output_file.txt 文件包含您键入的所有内容、您运行的程序的任何输出以及这些命令显示的任何错误消息的完整记录 — 完全跟您执行这些命令时的样子一样。

使用 script 命令

尽管诸如 bash -i |& tee output_file.txt 这样的 UNIX 和 Linux 命令并不那么复杂,但是要键入它们、记住 "|" 和 "&" 字符的正确顺序、记住 tee 命令等等,也是很麻烦的。大多数 UNIX 和 Linux 系统上可用的一个更为简单的解决方案是 script 命令,它可以为您做到所有这一切。script 命令启动一个子 shell,并将您键入的所有内容、您运行的任何程序的所有输出以及这些程序产生的任何错误的一份副本保存到一个输出文件。如果您没有指定用来保存所有内容的文件的名称,script 命令会创建一个叫做 typescript 的文件,但是您也可以在命令行指定将被写入内容的文件的名称。例如,下面这个命令将您键入的所有内容、所有程序输出和任何错误消息捕获到 output_file.txt 文件:

    script output_file.txt

类似于使用交互式 shell(前一节已讨论),通过键入 exit 命令(大多数系统上也可以按 Control-d 组合键)退出 script 命令并关闭它的输出文件。

如果比较由上一节讨论的交互式 shell 机制产生的输出文件的内容和使用 script 命令产生的输出文件的内容,您马上会注意到,script 命令产生的文件通常包含控制字符,即退格、回车、用于显示某些提示的特殊字符以及您编辑前一个 shell 命令时使用的字符等等。script 命令创建的输出文件包含这些字符,因为它们包含您键入的所有内容的完好记录,不包含 shell 是怎么解释它的。使用前一节讨论的交互式 shell 机制产生的输出文件不包含这些字符,因为它们包含在退格和回车这类控制字符被处理之后最终发送到 shell 的内容。

使用您喜欢的文本编辑器清理 script 输出文件比较容易,网上有各种清理脚本可用。我喜欢的清理机制来自 Perl Monks 网站,使用一个简单的 Perl 命令以及标准的 UNIX 和 Linux col 命令(该命令将输出中的控制字符过滤出来,然后再将其作为输入),以清理 script 命令产生的输出文件。例如,要创建名为 output_file.txt 的 script 输出文件的一个干净副本(名为 output_file.txt.clean),您执行 清单 1 中所示的命令。

清单 1. 清理 script 输出
    cat output_file.txt | \
      perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' |\
        col -b > output_file.txt.clean

如果您经常做这类事情,可能想要创建一个小的 shell 脚本来自动化这一过程,以防在第二行键入替代的 Perl 命令时出问题。清单 2 是一个做这件事的小 shell 脚本。

清单 2. 一个用于清理 script 输出的 shell 脚本
    #!/bin/bash

    if [ $# -ne 2 ] ; then 
      echo "Usage: cleanup script-file output-file"
      exit
    fi

    cat $1 | \
      perl -pe 's/\e([^\[\]]|\[.*?[a-zA-Z]|\].*?\a)//g' |\
        col -b > $2

Shell 重定向、前一节讨论的交互式 shell 命令和本节讨论的 script 命令,都是用于捕获您可以在几乎每种 UNIX 和 Linux 系统上使用的程序交互的机制。但是,一些 UNIX 系统提供附加的工具用于捕获程序交互。这些工具提供在特殊情况下有用的附加功能,下一节将会讨论。

平台特定的文本捕获实用工具

大多数 UNIX 和 Linux 系统只提供 script 命令来自动化捕获程序交互,但是 AIX 操作系统提供一个方便的实用工具,就叫做 capture,用于将特定屏幕的文本内容写到文件。在您想要展示一个运行操作屏幕的命令例子(比如文本编辑器)时,这很有帮助。尝试使用 shell 重定向或 script 命令将一个使用 vi 编辑器的例子捕获到文件,会创建一个输出文件,其中包含很多控制字符,并且基本上是难以理解的。

如果您没有在命令行指定输出将写入到的特定文件的名称,那么 AIX capture 命令会创建一个名为 screen.out 的文件。启动 capture 命令会创建一个 shell,在该 shell 中,您可以执行您想要执行的任何命令,直到屏幕显示您想要捕获的内容为止。此时,键入 Control-p 组合键,将屏幕内容写到输出文件。要终止 capture 命令,简单地键入 exit 命令即可(大多数系统上也可按 Control-d)。

使用 capture 命令时,一定要记住,直到您键入 Control-p ,它才会捕获文本,多次键入 Control-p 只会覆盖输出文件,除非您用 -a 选项启动 capture 命令,告诉它附加到输出文件,而不是覆盖输出文件。

结束语

捕获与程序的交互是很常见的任务。尽管 UNIX 和 Linux shell 提供内置的机制用于将交互的特定部分写到文本文件,但是使用交互式 shell 或 script 命令会产生单个提供程序交互的完整连续记录的输出文件。产生这些输出文件(以及在必要时清理它们)的机制对于几乎所有UNIX 或 Linux 作者、开发人员或系统管理员都是有用的工具。

本系列的下一篇文章将讨论用于在 UNIX 和 Linux 系统上捕获显示整个屏幕或特定窗口的图像的标准工具。还要解释如何将这些图像转换成各种标准图形格式。

参考资料

学习

  • AIX and UNIX 专区:developerWorks 的“AIX and UNIX 专区”提供了大量与 AIX 系统管理的所有方面相关的信息,您可以利用它们来扩展自己的 UNIX 技能。
  • AIX and UNIX 新手入门:访问“AIX and UNIX 新手入门”页面可了解更多关于 AIX 和 UNIX 的内容。
  • AIX and UNIX 专题汇总:AIX and UNIX 专区已经为您推出了很多的技术专题,为您总结了很多热门的知识点。我们在后面还会继续推出很多相关的热门专题给您,为了方便您的访问,我们在这里为您把本专区的所有专题进行汇总,让您更方便的找到您需要的内容。
  • AIX and UNIX 下载中心:在这里你可以下载到可以运行在 AIX 或者是 UNIX 系统上的 IBM 服务器软件以及工具,让您可以提前免费试用他们的强大功能。
  • IBM Systems Magazine for AIX 中文版:本杂志的内容更加关注于趋势和企业级架构应用方面的内容,同时对于新兴的技术、产品、应用方式等也有很深入的探讨。IBM Systems Magazine 的内容都是由十分资深的业内人士撰写的,包括 IBM 的合作伙伴、IBM 的主机工程师以及高级管理人员。所以,从这些内容中,您可以了解到更高层次的应用理念,让您在选择和应用 IBM 系统时有一个更好的认识。
  • 浏览 技术书店,寻找关于此主题以及其他技术主题的书籍。

获得产品和技术

  • script 命令默认安装在大多数 UNIX 和 Linux 系统上,是 Linux 系统上 bsdutils 包的一部分,而 bsdutils 包本身又是 Linux 系统上 util-linux 包的一部分。您可以得到这个包的源代码,可以是您的系统的标准包的一部分,也可以从 ftp://ftp.us.kernel.org/pub/linux/utils/util-linux/ 得到。
  • Perl Monks Web 站点提供本文用来清理 script 输出的方法,并有很多其他针对 Perl 忠实用户的重要技巧。

讨论

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=AIX and UNIX
ArticleID=521210
ArticleTitle=在 UNIX 和 Linux 系统上捕获屏幕快照和程序交互: 第 1 部分,程序交互
publish-date=09132010