shell 创建文本菜单
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shell 创建文本菜单相关的知识,希望对你有一定的参考价值。
创建文本菜单核心是case命令,根据用户的选择来执行特定的命令。
创建菜单布局
使用echo命令打印字符,生成一个菜单,还可以包括标题等信息:
clear
echo
# -e 选项,打印特殊字符
echo -e " Sys Admin Menu
"
echo -e " 1. Display disk space"
echo -e " 2. Display logged on users"
echo -e " 3. Display memory usage"
echo -e " 0. Exit program
"
# -en 会去掉末尾的换行符,光标会留在行尾
echo -en " Enter option: "
# 获取用户输入,只期望获取到单个字符,-n选择限制只读1个字符,并且用户不用回车
read -n 1 option
clear命令,先清空当前会话的内容。
echo -e选项,可以打印特殊字符。
echo -en选项,会去掉末尾的换行符。这让菜单看上去更专业,光标会一直行尾等待用户输入。
获取用户输入
打印出菜单后,就要等待并获取用户输入。这步使用read命令。这里期望只要单个字符,所以用 -n 选项限制只读取一个字符。这样用户只需要输入一个数字,并且不用按回车。
创建菜单函数
把上面的部分封装成一个函数,这样,在任何时候只要调用函数,就能重现菜单。
创建桩函数
桩函数(stub function),是一个空函数,或者只有一个echo语句,说明最终这里需要什么内容:
function diskspace {
clear
echo "Display disk space"
}
这样,就不需要事先写出所有函数。菜单能够直接投入使用,之后在来实现具体的操作。
添加菜单逻辑
菜单布局和函数都有了,下面需要创建程序逻辑将二者结合起来。这里就需要case命令。
case命令根据菜单中输入的字符来调用相应的函数。用默认的case命令字符星号来处理所有不正确的菜单项。
下面就是这个完整的菜单脚本的例子:
#!/bin/bash
# 为脚本创建文本菜单
# --------------------
# 定义函数
# --------------------
# 打印菜单
function menu {
clear
echo
# -e 选项,打印特殊字符
echo -e " Sys Admin Menu
"
echo -e " 1. Display disk space"
echo -e " 2. Display logged on users"
echo -e " 3. Display memory usage"
echo -e " 0. Exit program
"
# -en 会去掉末尾的换行符,光标会留在行尾
echo -en " Enter option: "
# 获取用户输入,只期望获取到单个字符,-n选择限制只读1个字符,并且用户不用回车
read -n 1 option
}
function diskspace {
clear
df -k
}
function whoseon {
clear
who
}
function menusage {
clear
cat /proc/meminfo
}
# --------------------
# 函数主体
# --------------------
while [ 1 ]
do
# 菜单逻辑
menu
case $option in
0)
break ;;
1)
diskspace ;;
2)
whoseon ;;
3)
menusage ;;
*)
clear
echo "Wrong selection";;
esac
echo -en "
Hit any key to continue"
read -n 1 line
done
clear
菜单的显示效果如下:
Sys Admin Menu
1. Display disk space
2. Display logged on users
3. Display memory usage
0. Exit program
Enter option:
使用 select 命令
创建文本菜单的过程中,花了一半的精力在建立菜单布局和获取用户输入上。bash shell 提供了一个很容易上手的小工具,可以帮助自动完成这些工作。
select命令只需要一条命令就可以创建出菜单,然后获取输入并自动处理。命令格式如下:
select 选项变量 in "选项1" "选项2" "选项3"
do
命令
done
select命令会将每个选项自动加上编号,然后为选项显示一个由PS3环境变量定义的特殊提示符。所以还要定义PS3环境变量。
示例代码
这里是一个select命令的示例:
#!/bin/bash
# 为脚本创建文本菜单
function diskspace {
clear
df -k
}
function whoseon {
clear
who
}
function menusage {
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")
menusage ;;
*)
clear
echo "Wrong selection";;
esac
done
菜单效果如下:
$ menu2.sh
1) Display disk space 3) Display memory usage
2) Display logged on users 4) Exit program
Enter option:
使用这个工具可以快速的创建一个简易的菜单,不过视觉效果就差很多。
制作窗口(dialog包)
dialog包能够用ANSI转义控制字符在文本环境中创建标准的窗口对话框。
窗口部件
dialog包提供了很多窗口部件(widget),使用的时候命令格式如下:
dialog --widget parameters
常用的部件如下:
- msgbox部件:在窗口中显示一条简单的消息,会有一个OK按钮
- yesno部件:允许用户对窗口中显示的问题选择yes或no,会有两个按钮
- inputbox部件:提供一个简单的文本框区域来输入文本
- textbox部件:可以在窗口中显示大量信息,会生成一个滚动窗口
- menu部件:创建文本菜单,需要为每个选项提供一个选择标号和显示文本
- fselect部件:可以用来浏览文件和文件夹
更多窗口部件,后面会详细列出。
获取部件的输出
每个dialog部件都提供了两种形式的输出:
- 使用退出状态码
- 使用STDERR
返回选项
如果选择了YES或OK,返回退出状态码0。如果选择了Cancel或No,返回退出状态码1。可以用标准的$?变量来判断具体选择了哪个按钮。
返回数据
如果是返回数据,则会将数据发送到STDERR。可以用标准的bash shell方法来将STDERR输出重定向到另一个文件或文件描述符中:
dialog --inputbox "Enter your age: " 10 20 2>age.txt
具体怎么用可以参考下面的示例。
示例代码
内容比较多,感觉也不一定需要制作这么好的窗口来交换。编写脚本时记住两件事:
- 如果有按钮,检查dialog命令的退出状态码
- 否则就重定向STDERR来获取输出的值
前面的例子使用dialog包实现的示例代码:
#!/bin/bash
# 为脚本创建文本窗口菜单
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 menusage {
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 logged on users" 3 "Display memory usage" 0 "Exit program" 2> $temp2
if [ $? -eq 1 ]
then
break
fi
selection=$(cat $temp2)
case $selection in
0)
break ;;
1)
diskspace ;;
2)
whoseon ;;
3)
menusage ;;
*)
dialog --msgbox "Wrong selection" 10 30
esac
done
rm -f $temp 2> /dev/null
rm -f $temp2 2> /dev/null
这里用到了临时文件,并且使用mktemp命令来创建临时文件,看着挺专业。
安装dialog包
另外系统可能默认没有安装dialog包,要运行这个脚本,需要先安装dialog包:
[root@Ansible ~]# yum info dialog
已加载插件:fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
已安装的软件包
名称 :dialog
架构 :x86_64
版本 :1.2
发布 :5.20130523.el7
大小 :505 k
源 :installed
来自源:base
简介 : A utility for creating TTY dialog boxes
网址 :http://invisible-island.net/dialog/dialog.html
协议 : LGPLv2
描述 : Dialog is a utility that allows you to show dialog boxes (containing
: questions or messages) in TTY (text mode) interfaces. Dialog is called
: from within a shell script. The following dialog boxes are implemented:
: yes/no, menu, input, message, text, info, checklist, radiolist, and
: gauge.
:
: Install dialog if you would like to create TTY dialog boxes.
dialog部件详表
dialog部件
部件 | 描述 |
---|---|
calendar | 提供选择日期的日历 |
checklist | 显示多个选项(其中每个选项都能打开或关闭) |
form | 构建一个带有标签及文本字段(可以填内容)的表单 |
fselect | 提供一个文件选择窗口来浏览选择文件 |
gauge | 显示完成的百分比进度条 |
infobox | 显示一条消息,但不用等待回应 |
inputbox | 提供一个输入文本用的文本表单 |
inputmenu | 提供一个可编辑的菜单 |
menu | 显示可选择的一系列选项 |
msgbox | 显示一条消息,并要求用户选择OK按钮 |
pause | 显示一个进度条来显示暂停期间的状态 |
passwordbox | 显示一个文本框,但会隐藏输入的文本 |
passwordform | x牧场一个带标签和隐藏文本字段的表单 |
radiolist | 提供一组菜单选项,单只能选择其中一个。就是单选 |
tailbox | 用tail命令在滚动窗口中显示文件的内容 |
tailboxbg | 更tailbox一样,但是在后台模式中运行 |
textbox | 在滚动窗口中显示文件的内容 |
timebox | 提供一个选择小时、分钟和秒的窗口 |
yesno | 提供一条带有Yes和No按钮的简单消息 |
dialog选项
除了标准部件,还可以在dialog命令中定制不同的选项。这些选项可以让你全面定制窗口外观和操作。
dialog命令选项
选项 | 描述 |
---|---|
--add-widget | 继续下个对话框,直到按下Esc或Cancel按钮 |
--aspect ratio | 指定窗口宽度和高度的宽高比 |
--backtitle title | 指定显示在屏幕顶部背景上的标题 |
--begin x y | 指定窗口左上角的起始位置 |
--clear | 用默认的对话背景色来清空屏幕内容 |
--colors | 在对话文本中嵌入ANSI色彩编码 |
--cr-wrap | 在对话文本中允许使用换行符并强制换行 |
--create-rc file | 将示例配置文件的内容复制到指定的file文件中 |
--default-item string | 设定复选列表、表单或菜单对话中的默认项 |
--help | 显示dialog命令的帮助信息 |
--help-status | 当选定Help按钮后,在帮助信息后写入多选列表、单选列表或表单信息 |
--ignore | 忽略dialog不能识别的选项 |
--input-fd fd | 指定STDIN之外的另一个文件描述符 |
--insecure | 在password部件中键入内容时显示星号 |
--item-help | 为多选列表、单选列表或菜单中的每个标号在屏幕底部添加一个帮助栏 |
--keep-window | 不要清除屏幕上显示过的部件 |
--max-input size | 指定输入的最大字符串长度。默认为2048 |
--no-collapse | 不要将对话文本中的制表符转换成空格 |
--no-kill | 将tailbox对话框放到后台,并禁止该进程的SIGHUP信号 |
--no-shadow | 不要显示对话窗口的阴影效果 |
--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秒后退出并返回错误代码 |
--titel title | 指定对话窗口的标题 |
--trim | 从对话文本中删除前导空格和换行符 |
--visit-items | 修改对话窗口中制表符的停留位置,使其包括选项列表 |
dialog命令选项2
按钮的选项功能都差不多,单独列出在这里。可以重写对话窗口中的任意按钮标签:
选项 | 描述 |
---|---|
--cancel-label label | 指定Cancel按钮的替代标签 |
--defaultno | 将yes/no对话框的默认答案设为No |
--exit-label label | 指定Exit按钮的替代标签 |
--extra-button | 在OK按钮和Cancel按钮之间显示一个额外按钮 |
--extra-label label | 指定额外按钮的替代标签 |
--help-button | 在OK按钮和Cancel按钮后显示一个Help按钮 |
--help-label label | 指定Help按钮的替代标签 |
--nocancel | 隐藏Cancel按钮 |
--no-lable label | 为No按钮指定替代标签 |
--ok-label label | 指定OK按钮的替代标签 |
--yes-label label | 为Yes按钮指定替代标签 |
举例说明
- --title选项,允许你设置出现在窗口顶部的部件标题。
- --backtitle选项,是为脚本中的菜单创建公共标题的简便办法。
- --create-rc选项,dialog命令支持运行时配置。该命令会根据配置文件模板创建一份配置文件。
创建本地临时文件(mktemp)
在需要临时将内容保存到文件的时候,有个特殊命令可以用来创建临时文件。mktemp命令可以在/tmp目录中创建一个唯一的临时文件。shell会创建这个文件,但不用默认的umask值。它会将当前用户设置为文件的属主,并且只有属主有读写权限。
创建文件
默认情况下,mktemp会在当前目录中创建一个文件。使用命令的时候,需要指定一个文件名模板。模板可以包含任意文本文件名,在文件名末尾加上6个X(几个X都没关系,书上建议6位):
$ mktemp test1.XXXXXX
test1.Acrugq
$ ls -al test1*
-rw-------. 1 steed steed 0 12月 12 14:26 test1.Acrugq
$
mktemp命令会用6位字符码替换这6个X,从而保证文件名在目录中是唯一的。
在脚本中使用
在脚本中使用mktemp命令时,需要将文件名保存到变量中,这样就能在后面的脚本中引用了:
$ mktemp test2.XXXXXX
test2.leOFBZ
$ mktemp test2.XXXXXX
test2.5kDbKn
$ mktemp test2.XXXXXX
test2.domeOC
$ mktemp test2.XXXXXX
test2.CJX702
$ tempfile=$(mktemp test2.XXXXXX)
$ exec 3>>$tempfile
$ echo "test2 Line1" >&3
$ echo "TEST2 LINE2" >&3
$ exec 3>&-
$ cat $tempfile
test2 Line1
TEST2 LINE2
$ ls -al test2*
-rw-------. 1 steed steed 0 12月 12 14:41 test2.5kDbKn
-rw-------. 1 steed steed 0 12月 12 14:41 test2.CJX702
-rw-------. 1 steed steed 0 12月 12 14:41 test2.domeOC
-rw-------. 1 steed steed 0 12月 12 14:41 test2.leOFBZ
-rw-------. 1 steed steed 24 12月 12 14:41 test2.tMVTwN
$ rm -f $tempfile 2> /dev/null
$ ls -al test2*
-rw-------. 1 steed steed 0 12月 12 14:41 test2.5kDbKn
-rw-------. 1 steed steed 0 12月 12 14:41 test2.CJX702
-rw-------. 1 steed steed 0 12月 12 14:41 test2.domeOC
-rw-------. 1 steed steed 0 12月 12 14:41 test2.leOFBZ
$
这里先创建了几个临时文件,干扰一下。使用的时候,创建了文件描述符3来使用,使用完之后关闭了文件描述符。最后精确的把用完的临时文件给删除了。
在/tmp目录创建临时文件
-t选项会强制mktemp命令在系统的临时目录创建文件。此时返回的就是创建的文件的全路径:
$ mktemp -t test3.XXXXXX
/tmp/test3.aPIXIy
$
创建临时目录
-d选项则是创建一个临时目录。如果要在/tmp目录下创建临时目录,就是-dt:
$ mktemp -d dir.XXXXXX
dir.aBDmsd
$ mktemp -dt dir.XXXXXX
/tmp/dir.pqW927
$
以上是关于shell 创建文本菜单的主要内容,如果未能解决你的问题,请参考以下文章