目录
1、创建文本菜单
1.1、创建菜单布局
1.2、创建菜单函数
1.3、添加菜单逻辑
1.4、整合shell脚本菜单
1.5、使用select命令
2、制作窗口
2.1、dialog包
2.1.1、msgbox部件
2.1.2、yesno部件
2.1.3、inputbox部件
2.1.4、textbox部件
2.1.6、fselect部件
2.2、dialog选项
2.3、在脚本中使用dialog命令
3、使用图形
3.1、KDE环境
3.1.1、kdialog部件
3.1.2、使用kdialog
3.2、GNOME环境
3.2.1、zenity部件
3.2.2、在脚本中使用zenity
完整笔记请前往此处获取:https://download.csdn.net/download/qq_55908180/88366003
使用菜单是创建交互式shell脚本最常用的方法。提供各种选项可以帮助脚本用户了解脚本能做什么和不能做什么。
shell脚本菜单的核心是case命令。case命令会根据用户在菜单上的选择来执行特定命令。
创建菜单的第一步显然是决定在菜单上显示哪些元素以及想要显示的布局方式。
为了更好地显示菜单,在创建菜单前,要先清空显示器上已有的内容。
clear命令用当前终端会话的terminfo数据来清理出现在屏幕上的文本。运行clear命令之后,可以用echo命令来显示菜单元素。
默认情况下,echo命令只显示可打印文本字符。在创建菜单项时,非可打印字符通常也很有用,
比如制表符和换行符。要在echo命令中包含这些字符,必须用-e选项。因此,命令如下:
创建菜单的最后一步是获取用户输入,这步用read命令。因为我们期望只有单字符输入,所以在read命令中用了-n选项来限制只读取一个字符。这样用户只需要输入一个数字,也不用按回车键:
read -n 1 option
shell脚本菜单选项作为一组独立的函数实现起来更为容易。这样就能创建出简洁、准确、容易理解的case命令。
要做到这一点,你要为每个菜单选项创建独立的shell函数。创建shell菜单脚本的第一步是决定你希望脚本执行哪些功能,然后将这些功能以函数的形式放在代码中。
通常我们会为还没有实现的函数先创建一个桩函数( stub function )。桩函数是一个空函数,或者只有一个echo语句,说明最终这里里需要什么内容。
function diskspace {
clear
echo "This is where the diskspace commands will go"
}
还有一点有助于制作shell脚本菜单,那就是将菜单布局本身作为一个函数来创建。
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
}
前面已经建好了菜单布局和函数,接下来只需要创建程序逻辑把二者结合起来就行了,这就要用到case命令。case命令应该根据菜单中输入的字符来调用相应的函数。用默认的case命令字符(星号) 来处理所有不正确的菜单项是种不错的做法。下面有一个经典的在菜单中使用case命令的用法。如:
menu
case $option in
0)
break ;;
1)
diskspace ;;
2)
whoseon ;;
3)
memusage ;;
*)
clear
echo "Sorry,wrong selection";;
esac
这段代码首先用menu函数清空屏幕并显示菜单。menu函数中的read命令会一直等待,直到用户在键盘上键入了字符。然后,case命令就会接管余下的处理过程。case命令会基于返回的字符调用相应的函数。在函数运行结束后,case命令退出。
#!/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
结果如下所示:
这个菜单创建了三个函数,利用常见的命令提取Linux系统的管理信息。它使用while循环来一直菜单,除非用户选择了选项o,这时,它会用break命令来跳出while循环。
可以用这个模板创建任何shell脚本菜单界面。它提供了一种跟用户交互的简单途径。
select命令可以很快的创建出菜单,然后获取输入的答案并自动处理。格式如下:
select variable in list
do
commands
done
list参数是由空格分隔的文本选项列表,这些列表构成了整个菜单。select命令会将每个列表项显示成一个带编号的选项,然后为选项显示一个由PS3环境变量定义的特殊提示符。
接下来有一个select命令的简单示例。
#!/bin/bash
#using select in the menu
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包能够用ANSI转义控制字符在文本环境中创建标准的窗口对话框,我们可以轻而易举地把这些对话框融入自己的shell脚本中,借此与用户进行交互。
首先,要下载该包:sudo apt-get install dialog
dialog命令使用命令行参数来决定生成哪种窗口部件( widget )。部件是dialog包中窗口元素类型的术语。
部件 |
描述 |
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
每个dialog部件都提供了两种形式的输出:1、使用STDERR;2、使用退出状态码
msgbox部件是对话框中最常见的类型。它会在窗口中显示一条简单的消息,直到用户单击OK按钮后才消失。使用msgbox部件时要用下面的格式。
dialog --msgbox text height width
text参数是你想在窗口中显示的字符串。dialog命令会根据由height和width参数创建的窗口的大小来自动换行。如果想在窗口顶部放一个标题,也可以用--title参数,后接作为标题的文本。下面有一个使用msgbox的部件的例子:
yesno部件进一步扩展了msgbox部件的功能,允许用户对窗口中显示的问题选择yes或no。它会在窗口底部生成两个按钮:一个是Yes,一个是No。用户可以用鼠标、制表符键或者键盘方向键来切换按钮。要选择按钮的话、用户可以按下空格键或者回车键。如:
inputbox部件为用户提供了一个简单的文本框区域来输入文本字符串。
dialog命令会将文本字符串的值发给sTDERR。你必须重定向STDERR来获取用户输人。
如:
如图所示:inputbox部件提供了两个按钮:确认(OK)和取消(Cancel)
textbox部件是在窗口中显示大量信息的极佳办法。它会生成一个滚动窗口来显示由参数所指定的文件中的文本。如:
menu部件允许创建之前所制作的文本菜单的窗口版本。只要为每个选项提供一个选择标号和文本就行了。如:
fselect部件在处理文件名时非常方便。不用强制用户键人文件名,你就可以用fselect部件来浏览文件的位置并选择文件名。如:
fselect选项后的第一个参数是窗口中使用的起始目录位置。
fselect部件窗口由左侧的目录列表、右侧的文件列表(显示了选定目录下的所有文件)和含有当前选定的文件或目录的简单文本框组成。可以手动在文本框键入文件名,或者用目录和文件列表来选定(使用空格键选择文件,将其加入文本框中)。
除了标准部件,还可以在dialog命令中定制很多不同的选项。已经看过了-title选项的用法。它允许你设置出现在窗口顶部的部件标题。
另外还有许多其他的选项可以让你全面定制窗口外观和操作。
在脚本中使用dialog命令不过就是动动手的事。你必须记住两件事:
1、如果有Cancel或No按钮,检查dialog命令的退出状态码;
2、重定向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)
dsikspace ;;
2)
whoseon ;;
3)
memusage ;;
0)
break ;;
*)
dialog --msgbox "Sorry,invalid selecion" 10 30
esac
done
rm -f $temp 2> /dev/null
rm -f $temp2 2> /dev/null
结果显示如下:
该脚本用while循环和一个真值常量创建了个无限循环来显示菜单对话。也就是说,执行完每个函数之后,脚本都会返回菜单。
由于menu对话包含了一个Cancel按钮,脚本会检查dialog命令的退出状态码,以防用户按下Cancel按钮退出。因为它是在while循环中,所以退出该菜单就跟用break命令跳出while循环一样简单。
脚本用mktemp命令创建两个临时文件来保存dialog命令的数据。
第一个临时文件$temp用来保存df和meminfo命令的输出,这样就能在textbox对话中显示它们了;
第二个临时文件$temp2用来保存在主菜单对话中选定的值。
如果想在脚本中加入更多的图形元素。KDE和GNOME桌面环境都扩展了dialog命令,包含了可以在各自环境下生成X Window 图形化部件的命令。这里将描述kdialog和zenity包,它们各自为KDE和GNOME桌面提供了图形化窗口部件。
KDE图形化环境默认包含kdialog包。kdialog包使用kdialog命令在KDE桌面上生成类似于dialog式部件的标准窗口。生成的窗口能跟其他KDE应用窗口很好地融合,不会造成不协调的感觉。
与dialog命令一样,该命令是使用命令行选项来指定使用哪类的窗口部件。格式如下:
kdialog display-options window-options arguments
checklist和radiolist部件允许你在列表中定义单独的选项以及它们默认是否选定。如:
指定为on的选项会在多选列表中高亮显示。要选择或取消选择多选列表中的某个选项,只要单击它就行了。如果选择了OK按钮,kdialog就会将标号值发到STDOUT上。
可以在shell脚本中使用kdialog窗口部件,方法与dialog部件相似。最大的不同是kdialog窗口部件用STDOUT来输出值,而不是STDERR。
例子:把之前创建的系统管理菜单转换为KDE应用;如:
#!/bin/bash
#using kdialog to create a menu
temp=$(mktemp -t temp.XXXXXX)
temp2=$(mktemp -t temp2.XXXXXX)
function diskspace {
fd -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
kdialog --menu "Sys Admin Menu" "1" "Display diskspace" "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图形化环境支持两种流行的可生成标准窗口的包:1、gdialog 2、zenity
zenity允许用命令行选项创建不同的窗口部件。
注意:zenity命令行程序与kdialog和dialog程序的工作方式有些不同。许多部件类型都用另外的命令行选项定义,而不是作为某个选项的参数。如:calendar选项会产生一个整月的日历:
当在日历中选择了日期时,zenity命令会将值返回到STDOUT中,就和kdialog一样。
zenity 还有一个比较不错的窗口是文件选择选项。如:zenity --file-selection
可以用对话窗口来浏览系统上任意一个目录位置,并选择文件。当选定文件时,zenity命令会返回完整的文件路径名。
zenity没有沿袭dialog和kdialog中所采用的选项惯例,因此,将已有的交互式脚本迁移到zenity上要花点工夫。
在把系统管理菜单从kdialog迁移到zenity的过程中,需要对部件定义做大量的工作。如:
#!/bin/bash
#using zenity to create a menu
temp=$(mktemp -t temp.XXXXXX)
temp2=$(mktemp -t temps.XXXXXX)
function diskspace {
df -k > $temp
zenity --text-info --title "Disk space" --filename=$temp --width 750 --height 10
}
function whoseon {
who > $temp
zenity --text-info --title "Logged in users" --filename=$temp --width 500 --height 10
}
function memusage {
cat /proc/meminfo > $temp
zenity --text-info --title "Memory usage" --filename=$temp --width 300 --height 500
}
while [ 1 ]
do
zenity --list --radiolist --title "Sys Admin Menu" --column "Select" --column "Menu Item" FALSE "Display diskspace" 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
结果显示如下:
由于zenity并不支持菜单对话窗口,所以单选列表窗口来作为主菜单,该单选列表用了两列,每列都有一个标题:第一列包含用于选择的单选按钮,第二列是选项文本。单选列表也不用选项里的标号。当选定一个选项时,该选项的所有文本都会返回到STDOUT。必须在case中使用选项的全文本。如果文本中有任何空格,就需要给文本加上引号。