禅道博客

分享专业技术知识,文章内容干货满满

读书笔记--《Linux命令行与shell脚本编程大全》第十八章

2022-10-12 09:00:00
李阳
原创 118
摘要:本技术博客为《Linux命令行与shell脚本编程大全》第十八章内容总结,包含创建文本菜单、制作窗口和使用图形。

一、创建文本菜单

创建交互式shell脚本最常用的方法是使用菜单。

shell脚本菜单的核心是case命令。

1.1.创建菜单布局

clear命令用当前终端会话的terminfo数据来清理出现在屏幕上的文本。运行clear命令之后,可以用echo命令来显示菜单元素。

制表符和换行符,要在echo命令中包含这些字符,必须用-e选项。

file-download-526483.json

菜单拼接

file-download-526484.json

的-en选项会去掉末尾的换行符。

执行后如下

file-download-526485.json

创建菜单的最后一步是获取用户输入。

在read命令中用了-n选项来限制只读取一个字符。

file-download-526486.json

再次执行

file-download-526487.json

1.2.创建菜单函数

shell脚本菜单选项作为一组独立的函数实现起来更为容易。

通常我们会为还没有实现的函数先创建一个桩函数(stub function)。桩函数是一个空函数,或者只有一个echo语句,说明最终这里里需要什么内容。

function diskspace {

clear

echo "This is where the diskspace commands will go"

}

还有一点有助于制作shell脚本菜单,那就是将菜单布局本身作为一个函数来创建。

file-download-526488.json

1.3.添加菜单逻辑

case命令应该根据菜单中输入的字符来调用相应的函数。

file-download-526489.json

执行

file-download-526490.json

这段代码首先用menu函数清空屏幕并显示菜单。menu函数中的read命令会一直等待,直到用户在键盘上键入了字符。然后,case命令就会接管余下的处理过程。case命令会基于返回的

字符调用相应的函数。在函数运行结束后,case命令退出。

1.4.整合shell脚本菜单

下面是一个完整的菜单脚本的例子

file-download-527158.json

这个脚本首先创建了三个函数,都是常见的Linux系统的管理信息。再使用while一直循环显示菜单函数,除非用户选择0退出循环。

1.5.使用select命令

select命令只需要一条命令就可以创建出菜单,然后获取输入的答案并自动处理。

命令格式如下:

select variable in list

do

commands

done

list参数是由空格分隔的文本选项列表,这些列表构成了整个菜单。select命令会将每个列表项显示成一个带编号的选项,然后为选项显示一个由PS3环境变量定义的特殊提示符。

file-download-528339.json

二、制作窗口

dialog包最早是由Savio Lam创建的一个小巧的工具,现在由Thomas E. Dickey维护。

该包能够用ANSI转义控制字符在文本环境中创建标准的窗口对话框。

2.1.dialog包

dialog命令使用命令行参数来决定生成哪种窗口部件(widget)。一下是部件的说明。

  • calendar           提供选择日期的日历

  • checklist           显示多个选项(其中每个选项都能打开或关闭)

  • form                 构建一个带有标签以及文本字段(可以填写内容)的表单

  • fselect              提供一个文件选择窗口来浏览选择文件

  • gauge              显示完成的百分比进度条

  • infobox            显示一条消息,但不用等待回应

  • inputbox          提供一个输入文本用的文本表单

  • inputmenu       提供一个可编辑的菜单

  • menu               显示可选择的一系列选项

  • msgbox            显示一条消息,并要求用户选择OK按钮

  • pause               显示一个进度条来显示暂定期间的状态

  • passwordbox   显示一个文本框,但会隐藏输入的文本

  • passwordform 显示一个带标签和隐藏文本字段的表单

  • radiolist           提供一组菜单选项,但只能选择其中一个

  • tailbox             用tail命令在滚动窗口中显示文件的内容

  • tailboxbg         跟tailbox一样,但是在后台模式中运行

  • textbox            在滚动窗口中显示文件的内容

  • timebox           提供一个选择小时、分钟和秒数的窗口

  • yesno               提供一条带有Yes和No按钮的简单消息

要在命令行上指定某个特定的部件,需使用双破折线格式

dialog --widget parameters

其中 widget是表18-1中的部件名, parameters定义了部件窗口的大小以及部件需要的文本。

每个dialog部件都提供了两种形式的输出:

  • 使用STDERR

  • 使用退出状态码

可以用标准的bash shell方法来将STDERR输出重定向到另一个文件或文件描述符中。

dialog --inputbox "Enter your age:" 10 20 2>age.txt

2.1.1.msgbox部件

msgbox部件是对话框中最常见的类型。它会在窗口中显示一条简单的消息,直到用户单击OK按钮后才消失。使用msgbox部件时要用下面的格式。

dialog --msgbox text height width

text参数是你想在窗口中显示的字符串。dialog命令会根据由 heightwidth参数创建的窗口的大小来自动换行。,也可以用--title参数,后接作为标题的文本。

dialog --title Testing --msgbox "This is a test" 10 20

file-download-528697.json

2.1.2.yesno部件

yesno部件进一步扩展了msgbox部件的功能,允许用户对窗口中显示的问题选择yes或no。

例子:

dialog --title "Please answer" --yesno "Is this thing on?" 10 20

file-download-528698.json

dialog命令的退出状态码会根据用户选择的按钮来设置。如果用户选择了No按钮,退出状态码是1;如果选择了Yes按钮,退出状态码就是0。

file-download-528699.json

2.1.3.inputbox部件

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

inputbox提供了两个按钮:OK和Cancel。如果选择了OK按钮,命令的退出状态码就是0;反之,退出状态码就会是1。

例子:

dialog --inputbox "Enter your age:" 10 20 2>age.txt

file-download-528700.json

输入10后,查看执行状态码和重定向的输出文件age.txt

file-download-528701.json

2.1.4.textbox部件

textbox部件是在窗口中显示大量信息的极佳办法。它会生成一个滚动窗口来显示由参数所指定的文件中的文本。

例子:

dialog --textbox /etc/passwd 35 75

file-download-528702.json

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

2.1.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

file-download-528703.json

第一个参数定义了菜单的标题,之后的两个参数定义了菜单窗口的高和宽,而第四个参数则定义了在窗口中一次显示的菜单项总数。如果有更多的选项,可以用方向键来滚动显示它们。

在这些参数后面,你必须添加菜单项。第一个元素是用来选择菜单项的标号。每个标号对每个菜单项都应该是唯一的,可以通过在键盘上按下对应的键来选择。第二个元素是菜单中使用的文本。

dialog命令会将选定的菜单项文本发送到STDERR。可以根据需要重定向STDERR。

file-download-528704.json

2.1.6.fselect部件

fselect部件在处理文件名时非常方便。不用强制用户键入文件名,你就可以用fselect部件来浏览文件的位置并选择文件。

例子:

dialog --title "Select a file" --fselect $HOME/ 10 50 2>file.txt

file-download-528706.json

fselect选项后的第一个参数是窗口中使用的起始目录位置。fselect部件窗口由左侧的目录列表、右侧的文件列表(显示了选定目录下的所有文件)和含有当前选定的文件或目录的简单文本框组成。

可以手动在文本框键入文件名,或者用目录和文件列表来选定(使用空格键选择文件,将其加入文本框中)。

2.2.dialog选项

除了标准部件,还可以在dialog命令中定制很多不同的选项。

  • --add-widget          继续下个对话框,直到按下Esc或Cancel按钮

  • --aspect ratio          指定窗口宽度和高度的宽高比

  • --backtitle title        指定显示在屏幕顶部背景上的标题

  • --begin x y               指定窗口左上角的起始位置

  • --cancel-label label 指定Cancel按钮的替代标签

  • --clear                      用默认的对话背景色来清空屏幕内容

  • --colors                    在对话文本中嵌入ANSI色彩编码

  • --cr-wrap                  在对话文本中允许使用换行符并强制换行

  • --create-rc file          将示例配置文件的内容复制到指定的 file文件中①

  • --defaultno               将yes/no对话框的默认答案设为No

  • --default-item string 设定复选列表、表单或菜单对话中的默认项

  • --exit-label label        指定Exit按钮的替代标签

  • --extra-button           在OK按钮和Cancel按钮之间显示一个额外按钮

  • --extra-label label      指定额外按钮的替代标签

  • --help                         显示dialog命令的帮助信息

  • --help-button            在OK按钮和Cancel按钮后显示一个Help按钮

  • --help-label label       指定Help按钮的替代标签

  • --help-status              当选定Help按钮后,在帮助信息后写入多选列表、单选列表或表单信息

  • --ignore                      忽略dialog不能识别的选项

  • --input-fd fd               指定STDIN之外的另一个文件描述符

  • --insecure                   在password部件中键入内容时显示星号

  • --item-help                 为多选列表、单选列表或菜单中的每个标号在屏幕的底部添加一个帮助栏

  • --keep-window           不要清除屏幕上显示过的部件

  • --max-input size         指定输入的最大字符串长度。默认为2048

  • --nocancel                  隐藏Cancel按钮

  • --no-collapse              不要将对话文本中的制表符转换成空格

  • --no-kill                       将tailboxbg对话放到后台,并禁止该进程的SIGHUP信号

  • --no-label                     label为No按钮指定替代标签

  • --no-shadow               不要显示对话窗口的阴影效果

  • --ok-label                      label 指定OK按钮的替代标签

  • --output-fd fd              指定除STDERR之外的另一个输出文件描述符

  • --print-maxsize            将对话窗口的最大尺寸打印到输出中

  • --print-size                   将每个对话窗口的大小打印到输出中

  • --print-version              将dialog的版本号打印到输出中

  • --separate-output         一次一行地输出checklist部件的结果,不使用引号

  • --separator string          指定用于分隔部件输出的字符串

  • --separate-widget string 指定用于分隔部件输出的字符串

  • --shadow                        在每个窗口的右下角绘制阴影

  • --single-quoted              需要时对多选列表的输出采用单引号

  • --sleep sec                       在处理完对话窗口之后延迟指定的秒数

  • --stderr                            将输出发送到STDERR(默认行为)

  • --stdout                           将输出发送到STDOUT

  • --tab-correct                    将制表符转换成空格

  • --tab-len n                        指定一个制表符占用的空格数(默认为8)

  • --timeout sec                    指定无用户输入时, sec秒后退出并返回错误代码

  • --title title                         指定对话窗口的标题

  • --trim                                从对话文本中删除前导空格和换行符

  • --visit-items                      修改对话窗口中制表符的停留位置,使其包括选项列表

  • --yes-label                        label为Yes按钮指定替代标签

--backtitle选项是为脚本中的菜单创建公共标题的简便办法。如果你为每个对话窗口都指定了该选项,那么它在你的应用中就会保持一致,这样会让脚本看起来更专业。

2.3.在脚本中使用dialog命令

注意:

  • 如果有Cancel或No按钮,检查dialog命令的退出状态码;

  • 重定向STDERR来获得输出值。

例子:

file-download-529431.json

这段脚本用while循环和一个真值常量创建了个无限循环来显示菜单对话。这意味着,执行完每个函数之后,脚本都会返回继续显示菜单。

由于menu对话包含了一个Cancel按钮,脚本会检查dialog命令的退出状态码,以防用户按下Cancel按钮退出。因为它是在while循环中,所以退出该菜单就跟用break命令跳出while循环一样简单。

file-download-529432.json file-download-529433.json

三、使用图形

本节将描述kdialog和zenity包,它们各自为KDE和GNOME桌面提供了图形化窗口部件。

3.1.KDE环境

KDE图形化环境默认包含kdialog包。kdialog包使用kdialog命令在KDE桌面上生成类似于 dialog式部件的标准窗口。生成的窗口能跟其他KDE应用窗口很好地融合,不会造成不协调的感觉。

3.1.1.kdialog部件

kdialog命令使用命令行选项来指定具体使用哪种类型的窗口部件。

kdialog命令的格式:

kdialog display-options window-options arguments

选项表如下:

  • --checklist title [tag item status] 带有状态的多选列表菜单,可以表明选项是否被选定

  • --error text                                   错误消息框

  • --inputbox text [init]                    输入文本框。可以用init值来指定默认值

  • --menu title [tag item]                 带有标题的菜单选择框,以及用tag标识的选项列表

  • --msgbox text                              显示指定文本的简单消息框

  • --password text                            隐藏用户输入的密码输入文本框

  • --radiolist title [tag item status]   带有状态的单选列表菜单,可以表明选项是否被选定

  • --separate-output                        为多选列表和单选列表菜单返回按行分开的选项

  • --sorry text                                   “对不起”消息框

  • --textbox file [width] [height]       显示file的内容的文本框,可以指定width和height

  • --title title                                     为对话窗口的TitleBar区域指定一个标题

  • --warningyesno text                     带有Yes和No按钮的警告消息框

  • --warningcontinuecancel text      带有Continue和Cancel按钮的警告消息框

  • --warningyesnocancel text           带有Yes、No和Cancel按钮的警告消息框

  • --yesno text                                  带有Yes和No按钮的提问框

  • --yesnocancel text                        带有Yes、No和Cancel按钮的提问框

checklist和radiolist部件允许你在列表中定义单独的选项以及它们默认是否选定。

$kdialog --checklist "Items I need" 1 "Toothbrush" on 2 "Toothpaste" off 3 "Hair brush" on 4 "Deodorant" off 5 "Slippers" off

指定为on的选项会在多选列表中高亮显示。要选择或取消选择多选列表中的某个选项,只要 单击它就行了。如果选择了OK按钮,kdialog就会将标号值发到STDOUT上。

3.1.2.使用kdialog

以在shell脚本中使用kdialog窗口部件,方法类似于dialog部件。最大的不同是kdialog 窗口部件用STDOUT来输出值,而不是STDERR。

file-download-530084.json

3.2.GNOME环境

GNOME图形化环境支持两种流行的可生成标准窗口的包:

  • gdialog

  • zenity

3.2.1.zenity部件

zenity允许用命令行选项创建不同的窗口部件。

  • --calendar         显示一整月日历

  • --entry              显示文本输入对话窗口

  • --error              显示错误消息对话窗口

  • --file-selection 显示完整的路径名和文件名对话窗口

  • --info               显示信息对话窗口

  • --list                 显示多选列表或单选列表对话窗口

  • --notification   显示通知图标

  • --progress       显示进度条对话窗口

  • --question       显示yes/no对话窗口

  • --scale             显示可调整大小的窗口

  • --text-info       显示含有文本的文本框

  • --warning        显示警告对话窗口

3.2.2.在脚本中使用zenity

在将系统管理菜单从kdialog迁移到zenity的过程中,需要对部件定义做大量的工作。

file-download-530085.json

由于zenity并不支持菜单对话窗口,我们改用单选列表窗口来作为主菜单。

该单选列表用了两列,每列都有一个标题:第一列包含用于选择的单选按钮,第二列是选 项文本。单选列表也不用选项里的标号。当选定一个选项时,该选项的所有文本都会返回到 STDOUT。这会让case命令的内容丰富一些。必须在case中使用选项的全文本。如果文本中有 任何空格,你需要给文本加上引号。

发表评论
评论通过审核后显示。