內(nèi)容:
- 創(chuàng)建文本菜單
- 創(chuàng)建文本窗口部件
創(chuàng)建文本菜單
創(chuàng)建交互式shell腳本最常用的方法是使用菜單,它提供了各種選項(xiàng)幫助腳本用戶了解腳本能做到的和不能做的恍风。
shell腳本菜單的核心是case
命令蹦狂,該命令會根據(jù)用戶在菜單上的選擇來執(zhí)行特定命令。
下面我們逐步了解和創(chuàng)建基于菜單的shell腳本的步驟邻耕。
創(chuàng)建菜單布局
第一步是決定在菜單上顯示哪些元素以及想要顯示的布局方式鸥咖。
在創(chuàng)建菜單前,通常先清空顯示器上已有的內(nèi)容兄世。這樣能在干凈的啼辣,沒有干擾的環(huán)境中顯示菜單了。
clear
命令使用當(dāng)前終端的terminfo
數(shù)據(jù)來清理出現(xiàn)在屏幕上的文字御滩。運(yùn)行clear
命令后可以使用echo
命令顯示菜單元素鸥拧。
默認(rèn),echo命令只顯示可打印的文本字符削解。而在創(chuàng)建菜單時一些非文本字符也非常有用富弦,比如制表符和換行符。我們需要添加-e
選項(xiàng)使得echo
命令能解析包含在其中的非文本字符氛驮。
例如腕柜,
wsx@wsx:~/tmp$ echo -e "1.\tDisplay disk space"
1. Display disk space
這對于格式化菜單項(xiàng)布局非常方便,只需要幾個echo
命令就可以創(chuàng)建一個還不錯的菜單矫废。
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 menu\n\n"
echo -en "\t\tEnter an option: "
最后一行-en
選項(xiàng)去掉末尾換行符使得菜單更專業(yè)點(diǎn)盏缤,光標(biāo)會在行尾等待用戶輸入。
創(chuàng)建菜單的最后一步是獲取用戶輸入蓖扑。這一步用read
命令唉铜。因?yàn)槲覀冎黄谕脩羰褂脝巫址斎耄诿罴?code>-n選項(xiàng)進(jìn)行限定律杠。這樣用戶只需要輸入一個數(shù)字潭流,不用摁回車鍵竞惋。
read -n 1 option
創(chuàng)建菜單函數(shù)
shell腳本菜單選項(xiàng)作為一組獨(dú)立的函數(shù)實(shí)現(xiàn)起來更為容易。要做到這一點(diǎn)灰嫉,你要為每個菜單項(xiàng)創(chuàng)建獨(dú)立的shell函數(shù)拆宛。第一步是決定你希望腳本執(zhí)行那些功能,然后將這些功能以函數(shù)的形式放在代碼中熬甫。
通常我們會為還沒有實(shí)現(xiàn)的函數(shù)先創(chuàng)建一個樁函數(shù)胰挑,它是一個控函數(shù),或者只有一個echo語句椿肩,說明最終這里需要什么內(nèi)容瞻颂。**
function diskspace {
clear
echo "This is where the diskspace commands will do"
}
這允許菜單在我實(shí)現(xiàn)某個函數(shù)時仍然能正常操作。不需要我們寫出所有函數(shù)之后才能讓菜單投入使用郑象。函數(shù)從clear
命令開始贡这,這樣我們就能在一個干凈的屏幕上執(zhí)行該函數(shù),不會收到原先菜單的干擾厂榛。
另外盖矫,將菜單布局本身作為一個函數(shù)來創(chuàng)建有利于菜單制作。
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 menu\n\n"
echo -en "\t\tEnter an option: "
read -n 1 option
}
這樣我們能在任何時候調(diào)用該函數(shù)以此重現(xiàn)菜單击奶。
添加菜單邏輯
下一步我們需要創(chuàng)建程序邏輯將菜單布局和函數(shù)結(jié)合起來辈双。這需要使用case
命令。
case
命令應(yīng)該根據(jù)菜單中輸入的字符來調(diào)用相應(yīng)的函數(shù)柜砾,用case命令字符星號來處理所有不正確的菜單項(xiàng)湃望。
下面展示了典型菜單的case
用法:
menu
case $option in
0)
break ;;
1)
diskspace ;;
2)
whoseon ;;
3)
memusage ;;
*)
clear
echo "Sorry, wrong selection";;
esac
這里首先調(diào)用menu
函數(shù)清空屏幕并顯示菜單。menu
函數(shù)中的read
命令會一直等待痰驱,知道用戶在鍵盤上鍵入一個字符证芭。然后case
命令會接管余下的處理過程,基于字符調(diào)用相應(yīng)的函數(shù)担映。
整合shell腳本菜單
現(xiàn)在讓我們將前面的步驟全部組合起來废士,看看它們是如何協(xié)作的。
這是一個完整的菜單腳本例子:
wsx@wsx:~/tmp$ cat test14
#!/bin/bash
# simple script menu
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 menu\n\n"
echo -en "\t\tEnter an 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
使用:
Sys Admin Menu
1. Display disk space
2. Display logged on users
3. Display memory usage
0. Exit menu
Enter an option:
輸入1:
文件系統(tǒng) 1K-塊 已用 可用 已用% 掛載點(diǎn)
udev 4006080 0 4006080 0% /dev
tmpfs 807220 81004 726216 11% /run
/dev/sda4 305650672 14226064 275828680 5% /
tmpfs 4036100 1724 4034376 1% /dev/shm
tmpfs 5120 4 5116 1% /run/lock
tmpfs 4036100 0 4036100 0% /sys/fs/cgroup
/dev/sda3 524272 4684 519588 1% /boot/efi
tmpfs 807220 52 807168 1% /run/user/1000
tmpfs 807220 16 807204 1% /run/user/125
/dev/sda2 421886972 23340376 398546596 6% /media/wsx/存儲
Hit any key to continue
其他都可以自己測試一下蝇完,我就不贅言了官硝。
使用select命令
select
命令只需要一條命令就可以創(chuàng)建出菜單,然后獲取輸入的答案并自動處理短蜕。
命令格式如下:
select variable in list
do
commands
done
list
參數(shù)是由空格分隔的文本選項(xiàng)列表泛源,這些列表構(gòu)成了整個菜單。select
命令會將每個列表項(xiàng)顯示成一個帶編號的選項(xiàng)忿危,然后為選項(xiàng)顯示一個由PS3
環(huán)境變量定義的特殊提示符。
wsx@wsx:~/tmp$ cat smenu1
#!/bin/bash
# using select in the menu
function diskspace {
clear
df -k
}
function whoseon {
clear
who
}
function memusage {
clear
cat /proc/meminfo
}
PS3="Enter an 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")
memusage ;;
"Display memory usage")
memusage ;;
*)
clear
echo "Sorry, wrong selection";;
esac
done
clear
運(yùn)行會自動生成如下菜單項(xiàng):
wsx@wsx:~/tmp$ ./smenu1
1) Display disk space 3) Display memory usage
2) Display logged on users 4) Exit program
Enter an option:
在使用select
命令時没龙,記住存儲在變量中的結(jié)果值是整個文本字符串而不是跟菜單項(xiàng)相關(guān)聯(lián)的數(shù)字铺厨。文本字符串是要在case
語句中比較的內(nèi)容缎玫。
制作窗口
dialog
包能夠用ANSI轉(zhuǎn)義控制字符在文本環(huán)境中創(chuàng)建標(biāo)準(zhǔn)的窗口對話框。我們可以將這些對話框融入自己的shell腳本中解滓,借此與用戶進(jìn)行交互赃磨。這部分我們來學(xué)習(xí)如何使用dialog
包。
安裝:
sudo apt-get install dialog
dialog包
dialog
包使用命令行參數(shù)來決定生成哪種窗口部件(widget)洼裤。部件是dialog包中窗口元素的術(shù)語邻辉。
部件 | 描述 |
---|---|
calendar | 提供選擇日期的日歷 |
checklist | 顯示多個選項(xiàng)(其中每個選項(xiàng)都能打開或關(guān)閉) |
form | 構(gòu)建一個帶有標(biāo)簽以及文本字段(可以填寫內(nèi)容)的表單 |
fselect | 提供一個文件選擇窗口來瀏覽選擇文件 |
gauge | 顯示完成的百分比進(jìn)度條 |
infobox | 顯示一條消息,但不用等待回應(yīng) |
inputbox | 提供一個輸入文本用的文本表單 |
inputmenu | 提供一個可編輯的菜單 |
menu | 顯示可選擇的一系列選項(xiàng) |
msgbox | 顯示一條消息腮鞍,并要求用戶選擇OK按鈕 |
pause | 顯示一個進(jìn)度條來顯示暫定期間的狀態(tài) |
passwordbox | 顯示一個文本框值骇,但會隱藏輸入的文本 |
passwordform | 顯示一個帶標(biāo)簽的隱藏文本字段的表單 |
radiolist | 提供一組菜單選項(xiàng),但只能選擇其中一個 |
tailbox | 用tail命令在滾動窗口中顯示文件的內(nèi)容 |
tailboxbg | 跟tailbox一樣移国,但是在后臺模式中運(yùn)行 |
textbox | 在滾動窗口中顯示文件的內(nèi)容 |
timebox | 提供一個選擇小時吱瘩、分鐘和秒數(shù)的窗口 |
yesno | 提供一條帶有Yes和No按鈕的簡單消息 |
如上表所見,我們可以選擇很多不同的部件迹缀。只需要多花點(diǎn)功夫就可以讓腳本看起來更專業(yè)使碾。
要在命令行上指定某個特定的部件,需要使用雙破折線格式:
dialog --widget parameters
其中widget
是上表中某個特定的部件祝懂,parameters
定義了部件窗口的大小以及部件需要的文本票摇。
每個dialog部件都提供了兩種形式的輸出:
- 使用STDERR
- 使用退出狀態(tài)碼
可以通過dialog
命令的退出狀態(tài)碼來確定用戶選擇的按鈕。如果選擇了Yes或OK按鈕砚蓬,命令會返回狀態(tài)碼0
矢门。如果選擇了Cancer或No按鈕,命令會返回狀態(tài)碼1
怜械÷停可用標(biāo)準(zhǔn)的$?
變量來確定dialog
部件具體選擇了哪個按鈕。
如果部件返回了數(shù)據(jù)缕允,dialog
命令會將數(shù)據(jù)發(fā)送到STDERR峡扩。我們可以用標(biāo)準(zhǔn)的bash shell方法將其重定向到另一個文件或文件描述符中。
dialog --inputbox "Enter your age:" 10 20 2>age.txt
這條命令將文本框輸入的文本重定向到age.txt文本中障本。
msgbox部件
msgbox
部件是對話框中最常見的類型教届。它會在窗口中顯示一條簡單的信息,直到用戶點(diǎn)擊OK后消失驾霜。
使用格式:
dialog --msgbox text height width
text
參數(shù)是要在窗口顯示的字符串案训,height
與width
參數(shù)設(shè)定自動換行的窗口大小。如果想要在窗口加一個標(biāo)題粪糙,可以使用--title
參數(shù)强霎,后接作為標(biāo)題的文本。
例子:
dialog --title Testing --msgbox "This is a test" 10 20
輸入命令后蓉冈,消息框會顯示在終端上城舞。如果你的終端仿真器支持鼠標(biāo)轩触,可以單擊OK來關(guān)閉對話框项阴,也可以按下回車鍵肮柜。
yesno部件
該部件在窗口底部生成兩個按鈕:一個是Yes,一個是No酸舍。用戶可以用鼠標(biāo)拉馋、制表符或者鍵盤方向鍵來切換按鈕榨为。選擇按鈕則使用空格或者回車鍵。
下面是一個例子:
wsx@wsx:~$ dialog --title "Please answer" --yesno "Is this thing on?" 10 20
# 中間終端有輸出
wsx@wsx:~$ echo $?
0
dialog
命令的退出狀態(tài)碼會根據(jù)用戶選擇的按鈕來設(shè)置煌茴。選擇No返回1随闺,選擇Yes就是0。
inputbox部件
inputbox部件提供了一個簡單的文本框區(qū)域來輸入文本字符串景馁,dialog會將它傳到STDERR板壮,我們需要重定向獲得輸入。inputbox提供了兩個按鈕:OK和Cancel合住。如果選擇了OK绰精,命令退出狀態(tài)碼為0,否則為1透葛。
wsx@wsx:~/tmp$ dialog --inputbox "Enter your age:" 10 20 2>age.txt
wsx@wsx:~/tmp$ cat age.txt
24
如果你自己運(yùn)行過的話就會注意到該值后面沒有換行符笨使,這讓我們能夠輕松將文本內(nèi)容重定向到腳本變量中,以獲得用戶輸入的值僚害。
textbox部件
textbox部件是在窗口中顯示大量信息的極佳辦法硫椰。它會生成一個滾動窗口來顯示由參數(shù)所指定的文件中的文本。
wsx@wsx:~/tmp$ dialog --textbox /etc/passwd 15 45
/etc/passwd
文件內(nèi)容顯示在可滾動的文本窗口中萨蚕,可以用方向鍵來左右或上下滾動顯示文件的內(nèi)容靶草。窗口底部的行會顯示當(dāng)前查看文本處于文件中的哪個位置(百分比)。文本框只包含一個用來選擇退出部件的Exit按鈕岳遥。
menu部件
我們可以用這個部件來創(chuàng)建之前(上一篇筆記)中制作的文本菜單的窗口版本奕翔。只要為每個選項(xiàng)提供一個選擇標(biāo)號和文本就行。
wsx@wsx:~/tmp$ dialog --menu "Sys Admin Menu" 20 30 10 1 "Display disk space" 2 "Display users" 3 "Display memory usage" 4 "Exit" 2>test.txt
第一個參數(shù)定義了菜單的標(biāo)題浩蓉,之后的兩個參數(shù)定義了菜單窗口的高和寬派继,而第四個參數(shù)則定義了在窗口中一次顯示的菜單項(xiàng)總數(shù)。如果存在更多選擇捻艳,則有滾動條驾窟。
菜單項(xiàng)必須使用菜單對:第一個元素是用來選擇菜單項(xiàng)的標(biāo)號(必須唯一);第二個元素是菜單中使用的文本认轨。
dialog命令會將選定(鼠標(biāo)點(diǎn)擊或回車鍵或選擇OK)的菜單項(xiàng)文本發(fā)送到STDERR绅络。
fselect部件
該部件在處理文件名時非常方便。不用強(qiáng)制用戶鍵入文件名,我們就可以用fselect
部件來瀏覽文件的位置并選擇文件恩急。
使用格式:
wsx@wsx:~/tmp$ dialog --title "Select a file" --fselect $HOME/ 10 50 2>file.txt
第一個參數(shù)是窗口使用的其實(shí)目錄位置节视。fselect
部件窗口由左側(cè)的目錄列表、右側(cè)的文件列表和含有當(dāng)前選定的文件或目錄的簡單文本框組成假栓。可以手動在文本框鍵入文件名霍掺,或者用目錄和文件列表來選定(使用空格鍵選定)匾荆。
dialog選項(xiàng)
除了標(biāo)準(zhǔn)部件,dialog還有大量定制的選項(xiàng)杆烁。前面我們使用的title
就是一個牙丽。
下面顯示了命令可用的選項(xiàng):
選項(xiàng) | 描述 |
---|---|
--add-widget | 繼續(xù)下一個對話框直到按下Esc或Cancel選項(xiàng) |
--aspect ratio | 直到窗口寬度和高度的寬高比 |
--backtitle title | 直到顯示在屏幕頂部背景上的圖標(biāo) |
--begin x y | 指定窗口左上角的起始位置 |
--cancel-label label | 指定Cancel按鈕的替代標(biāo)簽 |
--clear | 用默認(rèn)的對話背景色來清空屏幕內(nèi)容 |
--colors | 在對話文本中嵌入ANSI色彩編碼 |
--cr-wrap | 在對話文本中允許使用換行符并強(qiáng)制換行 |
--create-rc file | 將示例配置文件的內(nèi)容復(fù)制到指定的file文件中 |
--defaultno | 將yes/no對話框的默認(rèn)答案設(shè)為no |
--default-item string | 設(shè)定復(fù)選列表、表單或菜單對話中的默認(rèn)項(xiàng) |
--exit-label label | 指定Exit按鈕的替代標(biāo)簽 |
--extra-button | 在OK按鈕和Cancel按鈕之間顯示一個額外按鈕 |
--extra-label label | 指定額外按鈕的替換標(biāo)簽 |
--help | 顯示dialog命令的幫助信息 |
--help-button | 在OK按鈕和Cancel按鈕后顯示一個Help按鈕 |
--help-label label | 指定Help按鈕的替換標(biāo)簽 |
--help-status | 當(dāng)選定Help按鈕后兔魂,在幫助信息后寫入多選列表烤芦、單選列表或表單信息 |
--ignore | 忽略dialog不能識別的選項(xiàng) |
--input-fd fd | 指定STDIN之外的另一個文件描述符 |
--insecure | 在passwd部件中鍵入內(nèi)容時顯示星號 |
--item-help | 為多選列表、單選列表或菜單中的每個標(biāo)號在屏幕底部添加一個幫助欄 |
--keep-window | 不要清除屏幕上顯示過的部件 |
--max-input size | 指定輸入的最大字符串長度析校。默認(rèn)為2048 |
--nocancel | 隱藏Cancel按鈕 |
--no-collapse | 不要將對話文本中的制表符轉(zhuǎn)換為空格 |
--no-kill | 將tailboxbg對話放到后臺构罗,并禁止該進(jìn)程的SIGHUP信號 |
--no-label label | 為No按鈕指定替換標(biāo)簽 |
--no-shadow | 不要顯示對話窗口的陰影效果 |
--ok-label label | 指定OK按鈕的替換標(biāo)簽 |
--output-fd fd | 指定除STDERR之外的另一個輸出文件描述符 |
--print-maxsize | 將對話窗口的最大尺寸打印到輸出中 |
--print-size | 將每個對話窗口的大小打印到輸出中 |
--print-version | 將dialog的版本號打印到輸出中 |
--separate-output | 一次一行地輸出checklist部件的結(jié)果,不使用引號 |
--separator string | 指定用于分隔部件輸出的字符串 |
--separate-widget string | 指定用于分隔部件輸出的字符串 |
--shadow | 在每個窗口右下角繪制陰影 |
--single-quoted | 需要時對多選列表的輸出采用單引號 |
--sleep sec | 在處理完對話窗口后延遲指定的秒數(shù) |
--stderr | 將輸出發(fā)送到STDERR(默認(rèn)) |
--stdout | 將輸出發(fā)送到STDOUT |
--tab-correct | 將制表符轉(zhuǎn)換為空格 |
--tab-len n | 指定一個制表符占用的空格數(shù)(默認(rèn)為8) |
--timeout sec | 指定無用戶輸入時智玻,sec秒后退出并返回錯誤代碼 |
--title title | 指定對話窗口的標(biāo)題 |
--trim | 從對話文本中刪除前導(dǎo)空格和換行符 |
--visit-tiems | 修改對話窗口制表符的停留位置遂唧,使其包括選項(xiàng)列表 |
--yes-label label | 為Yes按鈕指定替換標(biāo)簽 |
--backtitle
選項(xiàng)是為腳本中的菜單創(chuàng)建公共標(biāo)題的簡便辦法。上表提供的強(qiáng)大特性允許我們創(chuàng)建任何需要的窗口吊奢。
dialog命令支持運(yùn)行時配置盖彭。該命令會根據(jù)配置文件模板創(chuàng)建一份配置文件。dialog啟動時會先去檢查是否設(shè)置了DIALOGRC環(huán)境變量页滚,該變量會保存配置文件名信息召边。如果未設(shè)置該變量或未找到該文件,它會將$HOME/.dialogrc作為配置文件裹驰。如果這個文件還不存在的話就嘗試查找編譯時指定的GLOBALRC文件隧熙,也就是/etc/dialogrc。如果還不存在就用編譯時的默認(rèn)值邦马。
在腳本中使用dialog命令
必須記住兩件事:
- 如果有Cancel或No按鈕贱鼻,檢查dialog命令的退出狀態(tài)碼
- 重定向STDERR來獲得輸出值
接下來是一個簡單的實(shí)例,使用dialog部件生成我們之前(上一篇筆記)所創(chuàng)建的系統(tǒng)管理菜單滋将。
wsx@wsx-laptop:~$ cat menu3
#!/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 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 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 $temp 2> /dev/null
使用while循環(huán)加一個真值常量創(chuàng)建了一個無限循環(huán)來顯示菜單對話邻悬。當(dāng)執(zhí)行完每個函數(shù)后,腳本會返回繼續(xù)顯示菜單随闽。
腳本使用了mktemp命令創(chuàng)建兩個臨時文件來保存dialog命令的數(shù)據(jù)父丰。