核心是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 $
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。