第十七章 图形化桌面环境脚本编程
菜单式脚本通常会清空显示区域,然后显示可用的菜单项列表。用户可以按下与每个菜单项关联的字母或数字来选择相应的选项。
shell脚本菜单的核心是case命令.根据用户在菜单上的选择来执行相应的命令。
一般使用echo来显示文本字符.
最后使用read获取用户输入。
function menu {
clear
echo
echo -e "\t\t\tSys Admin Menu\n"
echo -e "\t1. Display disk space"
echo -e "\t2. Display logged on users"
echo -e "\t3. Display memory usage"
echo -e "\t0. Exit program\n\n"
echo -en "\t\tEnter option: "
read -n 1 option
}
menu
case $option in
0)
break ;;
1)
diskspace ;;
2)
whoseon ;;
3)
memusage ;;
*)
clear
echo "Sorry, wrong selection";;
esac
#!/bin/bash
function diskspace {
clear
df -k
}
function whoseon {
clear
who
}
function memusage {
clear
cat /proc/meminfo
}
function menu {
clear
echo
echo -e "\t\t\tSys Admin Menu\n"
echo -e "\t1. Display disk space"
echo -e "\t2. Display logged on users"
echo -e "\t3. Display memory usage"
echo -e "\t0. Exit program\n\n"
echo -en "\t\tEnter option: "
read -n 1 option
}
while [ 1 ]
do
menu
case $option in
0)
break ;;
1)
diskspace ;;
2)
whoseon ;;
3)
memusage ;;
*)
clear
echo "Sorry, wrong selection";;
esac
echo -en "\n\n\t\t\tHit any key to continue"
read -n 1 line
done
clear
while循环用于持续处理菜单,除非用户选择了选项0,即通过break命令跳出while循环。
创建文本菜单的一半工夫需要花费在建立菜单布局和获取用户输入上.
而 select命令只需要一个命令就可以创建出菜单,然后获取输入并自动处理。
select variable in list
do
commands
done
list参数是由空格分隔的菜单项列表,该列表构成了整个菜单。
select命令会将每个列表项显示成一个带编号的菜单项,然后显示一个由PS3环境变量定义的特殊提示符,指示用户做出选择。
对整合脚本菜单的菜单脚本优化:
#!/bin/bash
function diskspace {
clear
df -k
}
function whoseon {
clear
who
}
function memusage {
clear
cat /proc/meminfo
}
PS3="Enter option: "
select option in "Display disk space" "Display logged on users" "Display memory usage" "Exit program"
do
case $option in
"Exit program")
break ;;
"Display disk space")
diskspace ;;
"Display logged on users")
whoseon ;;
"Display memory usage")
memusage ;;
*)
clear
echo "Sorry, wrong selection";;
esac
done
clear
相较于图形化窗口而言,交互脚本中仍然欠缺很多东西.
dialog软件包最早是Savio Lam编写的一款小巧的工具,现在由Thomas E. Dickey负责维护。
dialog能够用ANSI转义控制字符,在文本环境中创建标准的窗口对话框。
可以轻而易举地将这些对话框融入自己的shell脚本中,以实现与用户的交互。
安装软件包
#Ubuntu Linux发行版
sudo apt-get install dialog
#基于Red Hat的发行版(比如CentOS)系统
sudo dnf install dialog
dialog命令使用命令行选项来决定生成的窗口部件.(widget)部件是代表某类窗口元素的术语。
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是表中的部件名,parameters定义了部件窗口的大小以及部件需要的文本。
每个dialog部件都提供了两种输出形式。
dialog命令的退出状态码能显示出用户选择的按钮。可以用$?变量来确定用户选择了dialog部件中的哪个按钮。
如果选择了Yes或OK按钮,dialog命令就会返回退出状态码0。
如果选择了Cancel按钮或No按钮,dialog命令就会返回退出状态码1。
如果部件返回了数据(比如菜单选择),那么dialog命令会将数据发送给STDERR。STDERR的输出可以重定向到另一个文件或文件描述符:
dialog --inputbox "Enter your age:" 10 20 2>age.txt
msgbox部件是最常见的对话框。它会在窗口中显示一条简单的消息,直到用户单击OK按钮后才消失。
dialog --msgbox _text height width_
text参数是在窗口中显示的字符串。
dialog命令会根据由 height 参数和 width 参数创建的窗口大小来自动换行。
如果想在窗口顶部放一个标题,可以用–title参数,后面跟上标题文本。
示例:
$ dialog --title Testing --msgbox "This is a test" 10 20
单击OK按钮或按下Enter键来关闭对话框。
yesno部件允许用户对窗口中显示的问题选择yes或no。
yesno部件在窗口底部生成两个按钮:一个是Yes,一个是No。
用户可以用鼠标、制表符键或者键盘方向键在这两个按钮间进行切换。按下空格键或者Enter键选择按钮。
$ dialog --title "Please answer" --yesno "Is this thing on?" 10 20
$ echo $?
1
如果选择了No按钮,那么退出状态码为1;如果选择了Yes按钮,则退出状态码为0。
inputbox部件为用户提供了一个简单的文本框区域来输入文本字符串。
dialog命令会将文本字符串发送到STDERR。必须重定向STDERR来获取用户输入.
inputbox部件提供了两个按钮:OK和Cancel。
选择了Canel按钮,dialog命令的退出状态码为1;否则退出状态码为0.
$ dialog --inputbox "Enter your age:" 10 20 2>age.txt
$ echo $?
0
$ cat age.txt
12$
textbox部件是在窗口中显示大量信息的好方法。它会生成一个滚动窗口来显示指定文件的内容。
$ dialog --textbox /etc/passwd 15 45
可以用方向键来左右或上下滚动显示文件的内容。窗口底行会显示当前查看的文本在整个文件中所处的位置(百分比)。
textbox部件只有一个用于退出的Exit按钮。
menu部件可以创建文本菜单的窗口版本。只要为每个菜单项提供选择标号和文本.
参数–menu "Sys Admin 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
select部件在处理文件名时非常方便。不用强制用户键入文件名,可以使用fselect部件来浏览文件的位置并选择文件.
$ dialog --title "Select a file" --fselect $HOME/ 10 50 2>file.txt
–fselect后的第一个参数指定了窗口使用的起始目录位置。
fselect部件窗口由左侧的目录列表、右侧的文件列表(显示了选定目录下的所有文件)和含有当前选定的文件或目录的简单文本框组成。
可以手动在文本框中输入文件名,也可以用目录和文件列表来选定(使用空格键选定文件,将其加入文本框中)。
可以在dialog命令中定制很多不同的选项.
选项 | 描述 |
---|---|
–add-widget | 继续下一个对话框,直到按下Esc键或单击Cancel按钮 |
–aspect ratio | 指定窗口的宽高比 |
–backtitle title | 指定显示在屏幕顶部背景上的标题 |
–begin x y | 指定窗口左上角的起始位置 |
–cancel-label label | 指定Cancel按钮的替代标签 |
–clear | 用默认的对话背导色来清空屏幕内容 |
–colors | 在对话文本中最入ANSI色彩编码 |
–cr-wrap | 在对话框文本中允许使用换行符并强制折行 |
–create-rc file | 将示例配置文件的内容复制到指定文件 |
–defaultno | 将yes/no对话框的默认答案设为No |
–default-item string | 设定复选列表,表单或菜单对话框中的默认项 |
–exit-label label | 指定Exit按钮的普代标签 |
–extra-button | 在OK按钮和Cancel按钮之间显示一个额外按钮 |
–extra-label label | 指定Extra按钮的替代标签 |
–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 1 |
–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 | 指定无用户输入时,多少秒后退出并返回错误代码 |
–title title | 指定对话窗口的标题 |
–trim | 从对话框文本中删除前导空格和换行符 |
–visit-items | 修改对话窗口中制表符的停留位置,使其包括菜单项列表 |
–yes-label label | 指定Yes按钮的替代标签 |
在脚本中使用dialog命令时
使用dialog部件来生成我们之前创建过的系统管理菜单:
$ cat dialogmenu
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
KDE桌面环境和GNOME桌面环境都扩展了dialog命令的思路,提供了可以在各自环境中生成X Window图形化部件的命令。
KDE图形化环境默认提供了kdialog软件包。
使用kdialog命令在KDE桌面上生成类似于dialog式部件的标准窗口。可以直接在shell脚本中创建能够和Windows相媲美的用户界面。
kdialog命令格式:
kdialog display-options window-options arguments
部件 | 描述 |
---|---|
–checklist {title ftag item status] | 带有状态:的多选列表菜单,可以表明选项是否被选定 |
–error text | 错误消息框 |
–inputbox text [init] | 输入文本框,可以用init来指定默认值 |
–menu title [tag item] | 带有标题的菜单选择框以及用标号标识的选项列表 |
–msgbox text | 显示指定文本的简单消息框 |
–password text | 隐藏用户输入的密码文本框 |
–radiolist title [tag item status] | 带有状态的单选列表菜单,可以表明选项是否被选定 |
–separate-output | 为多选列表和单选列表菜单返回按行分开的列表项 |
–sorry text | ”对不起”消息框 |
–textbox fle [width] [height] | 显示文件内容的文本框,可以指定width和height |
–title title | 为对话窗口的标题栏区域指定一个标题 |
–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 "Hairbrush" on 4 "Deodorant" off 5 "Slippers" off
指定为“on”的列表项会在多选列表中高亮显示。
要选择或取消选择某个列表项,单击即可。
如果选择了OK按钮,那么kdialog会将所选列表项的标号发送到STDOUT:
"1" "3"
当单击OK按钮或Cancel按钮时,kdialog命令会将每个标号作为一个字符串值返回到STDOUT。
脚本必须能解析结果值并将它们和原始值匹配起来。
在shell脚本中使用kdialog窗口部件,方法类似于dialog部件。
最大的不同在于kdialog窗口部件用STDOUT而不是STDERR来输出值。
将之前的dialog menu改为KDE应用:
#!/bin/bash
temp=$(mktemp -t temp.XXXXXX)
temp2=$(mktemp -t temp2.XXXXXX)
function diskspace {
df -k > $temp
kdialog --textbox $temp 1000 10
}
function whoseon {
who > $temp
kdialog --textbox $temp 500 10
}
function memusage {
cat /proc/meminfo > $temp
kdialog --textbox $temp 300 500
}
while [ 1 ]
do
dialog --menu "Sys Admin Menu" "1" "Display disk space" "2" "Display users" "3" "Display memory usage" "0" "Exit" > $temp2
if [ $? -eq 1 ]
then
break
fi
selection=$(cat $temp2)
case $selection in
1)
diskspace ;;
2)
whoseon ;;
3)
memusage ;;
0)
break ;;
*)
kdialog --msgbox "Sorry, invalid selection"
esac
done
GNOME图形化环境支持两种流行的可生成标准窗口的软件包。
zenity是大多数GNOME桌面Linux发行版中最常见的软件包(在Ubuntu和CentOS中默认安装).
部件 | 描述 |
---|---|
–calendar | 显示整月日历 |
–entry | 显示文本输入对话窗口 |
–error | 显示错误消息对话窗口 |
–file-selection | 显示完整的路径和文件名对话窗口 |
–info | 显示信息对话窗口 |
–list | 显示多选列表或单选列表对话窗口 |
–notification | 显示通知图标 |
–progress | 显示进度条对话窗口 |
–question | 显示yes/no对话窗口 |
–scale | 显示一人带有滑动条的比例尺对话裔口,可以选择一定范围内的数值 |
–text-info | 显示含有文本的文本框 |
–warning | 显示警告对话窗口 |
–calendar选项会产生一个整月日历,并会将选择的日期的值发送到STDOUT.
$ zenity --calendar
08/08/2023
–file-selection文件选择对话框,可以浏览系统中的任意目录并选择其中的文件。当选定文件时,会返回该文件的完整路径.
将系统管理菜单从kdialog迁移到zenity
#!/bin/bash
temp=$(mktemp -t temp.XXXXXX)
temp2=$(mktemp -t temp2.XXXXXX)
function diskspace {
df -k > $temp
zenity --text-info --title "Disk space" --filename=$temp --width 1000 --height 1000
}
function whoseon {
who > $temp
zenity --text-info --title "Logged in users" --filename=$temp --width 1000 --height 1000
}
function memusage {
cat /proc/meminfo > $temp
zenity --text-info --title "Memory usage" --filename=$temp --width 1000 --height 1000
}
while [ 1 ]
do
zenity --list --radiolist --title "Sys Admin Menu" --column "Select" --column "Menu Item" FALSE "Display disk space" FALSE "Display users" FALSE "Display memory usage" FALSE "Exit" > $temp2
if [ $? -eq 1 ]
then
break
fi
selection=$(cat $temp2)
case $selection in
"Display disk space")
diskspace ;;
"Display users")
whoseon ;;
"Display memory usage")
memusage ;;
Exit)
break ;;
*)
zenity --info "Sorry, invalid selection"
esac
done