Dialog: 入门教程

作者:Jeff Tranter

Linux 基于 Unix 操作系统,但也具有许多独特的和有用的内核特性和应用程序,这些特性和程序通常超越了 Unix 系统所提供的功能。“dialog”就是一个鲜为人知的瑰宝,它是一个实用程序,用于从 shell 脚本中创建外观专业的对话框。本文介绍了 dialog 实用程序的入门教程,并展示了如何以及在何处使用它。

作者:Jeff Tranter

如果您安装了最新版本的 Slackware Linux 发行版,您会看到其外观专业的安装过程;它是使用 dialog 实用程序创建的。

dialog 秉承 Unix 编写通用工具并协同工作的传统,允许使用任何 shell 脚本语言创建基于文本的彩色对话框。它支持八种类型的对话框

  • 是/否 对话框

  • 菜单对话框

  • 输入对话框

  • 消息对话框

  • 文本框

  • 信息框

  • 复选框列表

  • 单选框列表

Dialog 非常易于使用。如果您手边有键盘,这是一个您可以尝试的单行消息框示例。(注意:本文中的示例假设您正在运行与 Bourne 兼容的 shell 程序,例如 GNU bash。)

% dialog --title 'Message' --msgbox 'Hello, world!' 5 20

此示例创建一个标题为“Message”的消息框,其中包含问候语“Hello, world!”。该框高 5 行,宽 20 个字符,消息在框中居中显示。底部会出现一个“OK”按钮;按下 <enter> 会关闭菜单。

对话框类型

大多数对 dialog 的调用都采用类似的格式:一个可选的标题,对话框类型,要显示的文本,以及对话框的高度和宽度(以字符为单位)。接下来是特定于每种菜单类型的其他参数。让我们简要了解一下每种可用的类型。

“yesno”菜单与我们的第一个示例非常相似

% dialog --title "Message"  --yesno "Are you having\ fun?" 6 25

如果您尝试此示例,您将看到底部现在有两个按钮,分别标记为“Yes”和“No”。您可以使用光标键(或 <tab>)在按钮之间进行选择,并通过按 <enter> 进行选择。如果选择“Yes”,则返回到 shell 的退出状态将为 0,如果选择“No”,则为 1。

您可能希望尝试调整高度和宽度参数。如果宽度小于字符串长度,则字符串将换行(在单词边界处)。如果您使对话框太小,则字符将会丢失。

我们之前看到了消息框。“infobox”与之类似,只是它不等待用户选择“OK”按钮。这对于在操作进行时显示消息很有用。这是一个例子

% dialog --infobox "Please wait" 10 30 ; sleep 4

“inputbox”允许用户输入字符串。可以使用常用的编辑键,并且文本字段会在必要时滚动。用户输入数据后,它将被写入标准错误(或者更常见的是像本例中一样重定向到文件)

% dialog --inputbox "Enter your name:" 8 40 2>answer

“textbox”类型是一个简单的文件查看器;它接受文件名作为参数

% dialog --textbox /etc/profile 22 70

常用的移动键在这里起作用:光标键、Page Up、Page Down、Home 等。您可以按 <esc> 或 <enter> 退出。

“menu”类型允许创建用户可以从中选择的菜单选项。格式是

% dialog --menu <text> <height> <width>
<menu-height> [<tag><item>]

每个菜单项都包含一个“tag”字符串和一个关联的“item”字符串,两者都会显示。用户可以使用光标键并按下 <enter> 进行选择。所选的标签会写入标准错误。这是一个简单的例子

% dialog --menu "Choose one:" 10 30 3 1 red 2 green\ 3 blue

下一种类型是“checklist”。用户会看到一个选项列表,并且可以使用空格键单独切换每个选项的开或关

% dialog --checklist "Choose toppings:" 10 40 3 \
        1 Cheese on \
        2 "Tomato Sauce" on \
        3 Anchovies off

每个选项中的第三个字段是初始状态;-“on”或“off”。最后一种类型是“radiolist”,它与 checklist 基本相同,只是用户必须从互斥选项列表中选择一个选项。radiolist 类型以及此处显示的标题的替代形式是在 dialog 0.4 版本中引入的。

% dialog --backtitle "CPU Selection" \
  --radiolist "Select CPU type:" 10 40 4 \
        1 386SX off \
        2 386DX on \
        3 486SX off \
        4 486DX off
一个实际应用

前面的示例有些不切实际;dialog 通常在 shell 脚本中使用以执行一些实际工作。让我们看一个简单但有用的应用程序。我定期使用以下脚本将我的主目录备份到软盘

#!/bin/sh
# Backup all files under home directory to a single # floppy
# Display message with option to cancel
dialog --title "Backup" --msgbox "Time for backup \ of home directory. \
Insert formatted 3-1/2\" floppy and press <Enter> \ to start backup or \
<Esc> to cancel." 10 50
# Return status of non-zero indicates cancel
if [ "$?" != "0" ]
then
  dialog --title "Backup" --msgbox "Backup was \ canceled at your
  request." 10 50
else
  dialog --title "Backup" --infobox "Backup in \ process..." 10 50
  cd ~
  # Backup using tar; redirect any errors to a
  # temporary file
  # For multi-disk support, you can use the
  # -M option to tar
  tar -czf /dev/fd1 . >|/tmp/ERRORS$$ 2>&1
  # zero status indicates backup was successful
  if [ "$?" = "0" ]
    then
    dialog --title "Backup" --msgbox "Backup \
completed successfully." 10 50
    # Mark script with current date and time
    touch ~/.backup
  else
    # Backup failed, display error log
    dialog --title "Backup" --msgbox "Backup failed \ -- Press
<Enter>
    to see error log." 10 50
   dialog --title "Error Log" --textbox /tmp/ERRORS$$ 22 72
  fi
fi
rm -f /tmp/ERRORS$$
clear

为了自动运行此操作,我将这些行放在我的 .profile 文件中,以便在登录时调用备份脚本,如果自上次备份以来已过去 3 天以上

# do a backup if enough time has elapsed
find ~/.backup -mtime +3 -exec ~/.backup \;
一个更长的例子

Linux 内核的声卡驱动程序使用一个名为“configure”的程序来提示用户设置声音配置选项。它根据所选选项生成一个 C 头文件。基于 dialog 的替代方案可以提供一些优势,例如更专业的外观以及从菜单中随机选择选项的能力,而不是按线性顺序提问。

由于时间和空间限制,我只展示了声卡驱动程序配置脚本的部分(但功能齐全的)实现。这可以很容易地扩展到完全替换当前的 configure 程序。

完整的脚本如列表 1 所示。我想使用自顶向下的方法来解释它,这意味着从底部开始阅读列表。

脚本的最后一部分是一个 while 循环,它只是重复调用 shell 函数 main_menu。上面是实现主菜单的代码。我们向用户呈现三个选择,并将选择重定向到一个文件。然后,根据用户的选择,调用三个 shell 函数之一。

此脚本中最重要的菜单是下一个,即 config_menu 函数。同样,我们向用户呈现多个选择。请注意,在这种情况下,有一个选项可以将用户返回到主菜单。

继续向后阅读我们的列表,我们来到了 select_cards 函数。内核支持多个声卡,因此这里我们使用复选框列表向用户呈现可用的选择。“on_off”命令是一个实用程序函数,稍后将展示;如果其参数相等,则返回字符串“on”,否则返回“off”。这是复选框列表菜单所需的格式。请注意,命令的返回状态已检查。如果用户从菜单中选择“cancel”,则返回状态为非零,我们会立即返回而不进行任何更改。否则,我们设置适当的变量来指示已启用哪些声卡。

下一个函数,当我们向后阅读我们的列表时,是 view_summary 函数。这使用文本框类型来显示包含当前所选选项信息的文件。我们首先在文件中构建数据,然后再显示它。

我们的下一个函数是 select_dma。在这里,用户必须从四个互斥选项中选择一个,因此我们使用单选框列表。如果您自己尝试此示例,请注意 radiolist 类型是在 dialog 0.4 版本中添加的;如果您有旧版本,则必须使用复选框列表。

可用性

在上面,例程 select_irq 使用非常相似的代码来允许用户在我们的配置实用程序中选择最终选项。

此脚本的目的是生成一个 C 语言头文件,用于定义内核声卡驱动程序的编译选项。“save”函数执行此操作。请注意,在保存过程中会显示一个对话框。

在上面我们看到了之前提到的 on_off 函数。这避免了脚本中一些重复的代码。

最后,我们看到了 clean_up 例程,它允许用户从脚本中退出。在脚本的顶部,为配置选项和要使用的临时文件名定义了一些默认值。

配置实用程序仍然需要一些增强功能才能替换现有程序,包括更多的内核选项和错误检查,但该示例确实可以工作,并让您了解 dialog 可以做什么。我鼓励您输入并尝试一下。

高级功能

dialog 还可以做更多的事情。您可以创建和使用 dialogrc 文件来自定义对话框的颜色和外观。Dialog 还支持不提供颜色或图形字符的显示器。详细信息在 man 手册中给出。

Dialog 是“8 位干净”的,这意味着支持标准 US ASCII 以外的国际字符集。

更多应用

有关使用 dialog 的更多示例,您可以查看 dialog 源代码中包含的示例脚本。在 Slackware Linux 下,系统配置脚本可以在 /usr/lib/setup 中找到。

毫无疑问,dialog 有许多可能的用途。例如,您可以为不熟悉 shell 命令的 Linux 用户创建一个完全菜单驱动的界面。这甚至可以扩展为一个简单的公告板系统,允许用户阅读邮件和 Usenet 新闻、编辑文件等。

示例声卡驱动程序脚本可以扩展为用于配置所有内核编译选项的工具。

顺便说一句,dialog 具有相当的可移植性,并且应该可以在任何具有 curses 库的 Unix 兼容系统上运行,只需进行最少的更改。它也可以从任何 shell 脚本语言中使用。

列表 1. 声卡驱动程序配置实用程序

结论

Dialog 是一个简单而强大的实用程序,秉承了 Unix 传统,即让每个工具做好一件事。它可以为您的应用程序增添精致的外观,并使其更易于使用。

感谢 dialog 包的作者 Savio Lam,将 dialog 更新到 0.4 版本的 Stuart Herbert,以及在 Slackware Linux 发行版中编写基于 dialog 的安装脚本的 Patrick Volkerding。

(Jeff_Tranter@mitel.com) 是加拿大卡纳塔一家高科技电信公司的软件设计师。为了运行 Linux,他在 18 个月前购买了一台 PC,此后一直没有回头。他是 Linux Sound 和 CD-ROM HOWTO 文档的作者。

加载 Disqus 评论