读书笔记--《Linux命令行与shell脚本编程大全》第十八章
- 2022-10-12 09:00:00
- 李阳
- 原创 378
一、创建文本菜单
创建交互式shell脚本最常用的方法是使用菜单。
shell脚本菜单的核心是case命令。
1.1.创建菜单布局
clear命令用当前终端会话的terminfo数据来清理出现在屏幕上的文本。运行clear命令之后,可以用echo命令来显示菜单元素。
制表符和换行符,要在echo命令中包含这些字符,必须用-e选项。
菜单拼接
的-en选项会去掉末尾的换行符。
执行后如下
创建菜单的最后一步是获取用户输入。
在read命令中用了-n选项来限制只读取一个字符。
再次执行
1.2.创建菜单函数
shell脚本菜单选项作为一组独立的函数实现起来更为容易。
通常我们会为还没有实现的函数先创建一个桩函数(stub function)。桩函数是一个空函数,或者只有一个echo语句,说明最终这里里需要什么内容。
function diskspace {
clear
echo "This is where the diskspace commands will go"
}
还有一点有助于制作shell脚本菜单,那就是将菜单布局本身作为一个函数来创建。
1.3.添加菜单逻辑
case命令应该根据菜单中输入的字符来调用相应的函数。
执行
这段代码首先用menu函数清空屏幕并显示菜单。menu函数中的read命令会一直等待,直到用户在键盘上键入了字符。然后,case命令就会接管余下的处理过程。case命令会基于返回的
字符调用相应的函数。在函数运行结束后,case命令退出。
1.4.整合shell脚本菜单
下面是一个完整的菜单脚本的例子
这个脚本首先创建了三个函数,都是常见的Linux系统的管理信息。再使用while一直循环显示菜单函数,除非用户选择0退出循环。
1.5.使用select命令
select命令只需要一条命令就可以创建出菜单,然后获取输入的答案并自动处理。
命令格式如下:
select variable in list
do
commands
done
list参数是由空格分隔的文本选项列表,这些列表构成了整个菜单。select命令会将每个列表项显示成一个带编号的选项,然后为选项显示一个由PS3环境变量定义的特殊提示符。
二、制作窗口
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命令会根据由 height和 width参数创建的窗口的大小来自动换行。,也可以用--title参数,后接作为标题的文本。
dialog --title Testing --msgbox "This is a test" 10 20
2.1.2.yesno部件
yesno部件进一步扩展了msgbox部件的功能,允许用户对窗口中显示的问题选择yes或no。
例子:
dialog --title "Please answer" --yesno "Is this thing on?" 10 20
dialog命令的退出状态码会根据用户选择的按钮来设置。如果用户选择了No按钮,退出状态码是1;如果选择了Yes按钮,退出状态码就是0。
2.1.3.inputbox部件
inputbox部件为用户提供了一个简单的文本框区域来输入文本字符串。dialog命令会将文本字符串的值发给STDERR。你必须重定向STDERR来获取用户输入。
inputbox提供了两个按钮:OK和Cancel。如果选择了OK按钮,命令的退出状态码就是0;反之,退出状态码就会是1。
例子:
dialog --inputbox "Enter your age:" 10 20 2>age.txt
输入10后,查看执行状态码和重定向的输出文件age.txt
2.1.4.textbox部件
textbox部件是在窗口中显示大量信息的极佳办法。它会生成一个滚动窗口来显示由参数所指定的文件中的文本。
例子:
dialog --textbox /etc/passwd 35 75
可以用方向键来左右或上下滚动显示文件的内容。窗口底部的行会显示当前查看的文本处于文件中的哪个位置(百分比)。文本框只包含一个用来选择退出部件的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
第一个参数定义了菜单的标题,之后的两个参数定义了菜单窗口的高和宽,而第四个参数则定义了在窗口中一次显示的菜单项总数。如果有更多的选项,可以用方向键来滚动显示它们。
在这些参数后面,你必须添加菜单项。第一个元素是用来选择菜单项的标号。每个标号对每个菜单项都应该是唯一的,可以通过在键盘上按下对应的键来选择。第二个元素是菜单中使用的文本。
dialog命令会将选定的菜单项文本发送到STDERR。可以根据需要重定向STDERR。
2.1.6.fselect部件
fselect部件在处理文件名时非常方便。不用强制用户键入文件名,你就可以用fselect部件来浏览文件的位置并选择文件。
例子:
dialog --title "Select a file" --fselect $HOME/ 10 50 2>file.txt
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来获得输出值。
例子:
这段脚本用while循环和一个真值常量创建了个无限循环来显示菜单对话。这意味着,执行完每个函数之后,脚本都会返回继续显示菜单。
由于menu对话包含了一个Cancel按钮,脚本会检查dialog命令的退出状态码,以防用户按下Cancel按钮退出。因为它是在while循环中,所以退出该菜单就跟用break命令跳出while循环一样简单。
三、使用图形
本节将描述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。
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的过程中,需要对部件定义做大量的工作。
由于zenity并不支持菜单对话窗口,我们改用单选列表窗口来作为主菜单。
该单选列表用了两列,每列都有一个标题:第一列包含用于选择的单选按钮,第二列是选 项文本。单选列表也不用选项里的标号。当选定一个选项时,该选项的所有文本都会返回到 STDOUT。这会让case命令的内容丰富一些。必须在case中使用选项的全文本。如果文本中有 任何空格,你需要给文本加上引号。