【shell实战之】图形化桌面环境中的 脚本编程——创建文本窗口部件

使用文本菜单绝对没问题,但我们的交互脚本中仍然欠缺很多东西,尤其是相较于图形化窗
口而言。幸运的是,开源界里有些多才多智的人已经帮我们搞定了。
dialog 软件包最早是 Savio Lam 编写的一款小巧的工具,现在由 Thomas E. Dickey 负责维护。
dialog 能够用 ANSI 转义控制字符,在文本环境中创建标准的窗口对话框。你可以轻而易举地将
这些对话框融入自己的 shell 脚本中,以实现与用户的交互。本节将介绍 dialog 软件包并演示如
何在 shell 脚本中使用它。

注意 并不是所有的Linux发行版中都会默认安装dialog软件包。如果没有安装,那么鉴于其流
行程度,你应该也能在软件仓库中找到它。参考 Linux 发行版的特定文档可以了解如何
下载 dialog 软件包。在 Ubuntu Linux 发行版中,使用下列命令安装该软件包:
sudo apt-get install dialog
基于 Red Hat 的发行版(比如 CentOS)系统,使用 dnf 命令安装该软件包:
sudo dnf install dialog
软件包管理器会为你安装 dialog 软件包以及所需的库

dialog 软件包

dialog 命令使用命令行选项来决定生成哪种窗口部件(widget)。部件是代表某类窗口元素
的术语。dialog 软件包目前支持的部件类型如表 18-1 所示。

在这里插入图片描述

如表 18-1所示,有很多不同的部件可供选择,只要多花一点儿工夫,就可以让你的脚本更专业。
要在命令行中指定某个特定部件,需要使用双连字符格式:
dialog --widget parameters
其中,widget 是表 18-1 中的部件名,parameters 定义了部件窗口的大小以及部件需要的文本。
每个 dialog 部件都提供了两种输出形式。
 使用 STDERR。
 使用退出状态码。
dialog 命令的退出状态码能显示出用户选择的按钮。如果选择了 Yes 按钮或 OK 按钮,
dialog 命令就会返回退出状态码 0。如果选择了 Cancel 按钮或 No 按钮,dialog 命令就会返回
退出状态码 1。可以用$?变量来确定用户选择了 dialog 部件中的哪个按钮。
如果部件返回了数据(比如菜单选择),那么 dialog 命令会将数据发送给 STDERRSTDERR
的输出可以重定向到另一个文件或文件描述符:
dialog --inputbox "Enter your age:" 10 20 2>age.txt 
该命令会将文本框中输入的文本重定向到 age.txt 文件。
接下来将介绍一些在 shell 脚本中频繁用到的 dialog 部件。

1. msgbox 部件

msgbox 部件是最常见的对话框。它会在窗口中显示一条简单的消息,直到用户单击 OK 按
钮后才消失。msgbox 部件使用的命令格式如下:
dialog --msgbox text height width 
text 参数是你想在窗口中显示的字符串。dialog 命令会根据由 height 参数和 width 参
数创建的窗口大小来自动换行。如果想在窗口顶部放一个标题,可以用--title 参数,后面跟
上标题文本。来看一个 msgbox 部件的例子。
$ dialog --title Testing --msgbox "This is a test" 10 20 
在输入这条命令后,消息框会显示在你所用的终端仿真器的屏幕上,如图所示。

在这里插入图片描述

如果你的终端仿真器支持鼠标,可以单击 OK 按钮来关闭对话框。也可以用键盘命令来模拟
单击动作——按下 Enter 键。

2. yesno 部件

yesno 部件进一步扩展了 msgbox 部件的功能,允许用户对窗口中显示的问题选择 yes或 no。
它会在窗口底部生成两个按钮:一个是 Yes,一个是 No。用户可以用鼠标、制表符键或者键盘
方向键在这两个按钮间进行切换。要选择按钮的话,按下空格键或者 Enter 键即可。
来看一个使用 yesno 部件的例子。
$ dialog --title "Please answer" --yesno "Is this thing on?" 10 20 

上述代码会产生图所示的部件。

在这里插入图片描述

选择yes后
$ echo $? 
0
dialog 命令的退出状态码会根据用户选择的按钮来设置。如果用户选择了 No 按钮,那么
退出状态码为 1;如果用户选择了 Yes 按钮,则退出状态码为 0

3. inputbox 部件

inputbox 部件为用户提供了一个简单的文本框区域来输入文本字符串。dialog 命令会将
文本字符串发送到 STDERR。你必须重定向 STDERR 来获取用户输入。图显示了 inputbox
部件的外形。

在这里插入图片描述

inputbox 部件提供了两个按钮:OK 和 Cancel。如果选择了 Canel 按钮,
那么 dialog 命令的退出状态码为 1;否则,退出状态码为 0:
$ dialog --inputbox "Enter your age:" 10 20 2>age.txt 
$ echo $? 
0 
$ cat age.txt 
12$ 
注意,在使用 cat 命令显示文本文件的内容时,在该值后并没有换行符。这让你能够轻松
地将文件内容重定向到 shell 脚本变量,提取用户输入的字符串。

4. textbox 部件

textbox 部件是在窗口中显示大量信息的好方法。它会生成一个滚动窗口来显示指定文件的内容。
$ dialog --textbox /etc/passwd 15 45 
/etc/passwd 文件的内容会显示在可滚动的文本窗口中,如图所示。

在这里插入图片描述

可以用方向键来左右或上下滚动显示文件的内容。窗口底行会显示当前查看的文本在整个文
件中所处的位置(百分比)。textbox 部件只有一个用于退出的 Exit 按钮。

5. menu 部件

menu 部件可以创建一个文本菜单的窗口版本。只要为每个菜单项提供选择标号和文本就行:
$ dialog --menu "Sys Admin Menu" 20 30 10 1 "Display disk space" 
2 "Display users" 3 "Display memory usage" 4 "Exit" 2> test.txt 
第一个参数--menu "Sys Admin Menu"定义了菜单的标题,后续两个参数 2030 定义
了菜单窗口的高和宽,第四个参数 10 定义了一次在窗口中显示的菜单项总数。如果还有更多的
菜单项,可以用方向键来滚动显示。
在这些参数之后,必须添加成对的菜单项。第一个元素是用来选择该菜单项的标号。每个标
号都是唯一的,可以通过在键盘上按下对应的键来选择。第二个元素是菜单项文本。图展示
了由示例命令生成的菜单。

在这里插入图片描述

如果用户通过按下标号对应的键选择了某个菜单项,则菜单项会高亮显示但不会被选定。直
到用户用鼠标或 Enter 键选择了 OK 按钮,该菜单项才算最终选定。dialog 命令会将选定的菜
单项文本发送到 STDERR。可以根据需要重定向 STDERR

6. fselect 部件

dialog 命令提供了几个非常炫的内置部件。fselect 部件在处理文件名时非常方便。不用
强制用户键入文件名,可以使用 fselect 部件来浏览文件的位置并选择文件,如图所示。

在这里插入图片描述

fselect 部件的命令格式如下所示:
$ dialog --title "Select a file" --fselect $HOME/ 10 50 2>file.txt 
--fselect 之后的第一个参数指定了窗口使用的起始目录位置。fselect 部件窗口由左侧
的目录列表、右侧的文件列表(显示了选定目录下的所有文件)和含有当前选定的文件或目录的
简单文本框组成。可以手动在文本框中输入文件名,也可以用目录和文件列表来选定(使用空格
键选定文件,将其加入文本框中)。

dialog 选项

除了标准部件,还可以在 dialog 命令中定制很多不同的选项。你已经看过了--title 选
项的用法,该选项允许设置出现在窗口顶部的部件标题。
另外还有许多其他的选项,可以全面定制窗口的外观和操作。表显示了 dialog 命令
中可用的选项。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

--backtitle 选项是为脚本中的菜单创建公共标题的简便办法。如果为每个对话窗口都指
定了该选项,那么标题在应用时就会保持一致,这样会让脚本看起来更专业。
由表 18-2 可知,可以重写对话窗口中的任意按钮标签。这个特性允许你创建所需的任何窗口。

在脚本中使用 dialog 命令

在脚本中使用 dialog 命令不过就是动动手的事,但要记住两条规则。
 如果有 Cancel 或 No 按钮,请检查 dialog 命令的退出状态码。
 重定向 STDERR 来获取输出值。
如果遵循这两条规则,你立刻就能够拥有具备专业风采的交互式脚本。下面这个例子使用
dialog 部件来生成我们之前创建过的系统管理菜单:

代码

#!/bin/bash 
# using dialog to create a menu 
temp=$(mktemp -t test.XXXXXX) 
temp2=$(mktemp -t test2.XXXXXX) 
function diskspace { 
 df -k > $temp 
 dialog --textbox $temp 20 60 
} 
function whoseon { 
 who > $temp 
 dialog --textbox $temp 20 50 
} 
function memusage { 
 cat /proc/meminfo > $temp 
 dialog --textbox $temp 20 50 
} 
while [ 1 ] 
do 
dialog --menu "Sys Admin Menu" 20 30 10 1 "Display disk space" 2 
 "Display users" 3 "Display memory usage" 0 "Exit" 2> $temp2 
if [ $? -eq 1 ] 
then 
 break 
fi 
selection=$(cat $temp2) 
case $selection in 
1) 
 diskspace ;; 
2) 
 whoseon ;; 
3) 
 memusage ;; 
0) 
 break ;; 
*) 
 dialog --msgbox "Sorry, invalid selection" 10 30 
esac 
done 
rm -f $temp 2> /dev/null 
rm -f $temp2 2> /dev/null
这段脚本用 while 循环和一个真值常量创建了无限循环的菜单对话。这意味着,执行完每
个函数之后,脚本都会继续显示菜单。
由于 menu 对话包含了一个 Cancel 按钮,因此脚本会检查 dialog 命令的退出状态码,以防
用户按下 Cancel 按钮退出。因为是在循环中,所以退出该菜单是使用 break 命令跳出 while 循环。
脚本用 mktemp 命令创建了两个临时文件来保存 dialog 命令的数据。第一个临时文件
$temp 用于保存 df 命令、who 命令和 meminfo 命令的输出,以便将其显示在 textbox 对话框
中(参见图 18-8)。第二个临时文件$temp2 用来保存在主菜单对话中选定的值。

运行结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值