十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
核心是case命令,根据用户的选择来执行特定的命令。
创新互联建站是网站建设专家,致力于互联网品牌建设与网络营销,专业领域包括成都做网站、网站设计、电商网站制作开发、小程序开发、微信营销、系统平台开发,与其他网站设计及系统开发公司不同,我们的整合解决方案结合了恒基网络品牌建设经验和互联网整合营销的理念,并将策略和执行紧密结合,且不断评估并优化我们的方案,为客户提供全方位的互联网品牌整合方案!
使用echo命令打印字符,生成一个菜单,还可以包括标题等信息:
clear
echo
# -e 选项,打印特殊字符
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"
# -en 会去掉末尾的换行符,光标会留在行尾
echo -en "\t\tEnter 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 "\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"
# -en 会去掉末尾的换行符,光标会留在行尾
echo -en "\t\tEnter 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 "\n\n\t\tHit 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:
创建文本菜单的过程中,花了一半的精力在建立菜单布局和获取用户输入上。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包能够用ANSI转义控制字符在文本环境中创建标准的窗口对话框。
dialog包提供了很多窗口部件(widget),使用的时候命令格式如下:
dialog --widget parameters
常用的部件如下:
更多窗口部件,后面会详细列出。
每个dialog部件都提供了两种形式的输出:
返回选项
如果选择了YES或OK,返回退出状态码0。如果选择了Cancel或No,返回退出状态码1。可以用标准的$?变量来判断具体选择了哪个按钮。
返回数据
如果是返回数据,则会将数据发送到STDERR。可以用标准的bash shell方法来将STDERR输出重定向到另一个文件或文件描述符中:
dialog --inputbox "Enter your age: " 10 20 2>age.txt
具体怎么用可以参考下面的示例。
内容比较多,感觉也不一定需要制作这么好的窗口来交换。编写脚本时记住两件事:
前面的例子使用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包:
[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部件
部件 | 描述 |
---|---|
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命令选项
选项 | 描述 |
---|---|
--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按钮指定替代标签 |
举例说明
在需要临时将内容保存到文件的时候,有个特殊命令可以用来创建临时文件。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来使用,使用完之后关闭了文件描述符。最后精确的把用完的临时文件给删除了。
-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
$