目录
❀dialog命令运用于linux❀
msgbox部件(消息框)
yesno部件(yesno框)
inputbox部件(输入文本框)
textbox部件(文本框)
fselect部件(文件选框)
passwordbox部件(密码框)
checklist部件(复选框)
calendar部件(显示日历)
gauge部件(进度框架)
❀管道文件和文件描述符❀
❀$?的含义❀
form部件(表单)
综合应用示例
❀dialog命令运用于linux❀
功能说明:dialog 工具是一个可以和shell脚本配合使用的文本界面下的创建对话框的工具。
(ps.dialog实用程序是基于ncurses库的。Ncurses是一个用于在文本终端上创建图形用户界面的库,它允许开发者创建基于文本的用户界面,而无需依赖图形环境或窗口系统。这使得ncurses库非常适合在命令行环境下创建交互式的用户界面。dialog实用程序利用ncurses库提供的功能,允许用户在终端中以对话框的形式进行交互。它可以用于创建各种对话框,如菜单、输入框、消息框等,使得用户能够在命令行环境下进行简单的图形化交互操作。Ncurses通常被发音为 "en-curses"。 "en" 是字母 "n" 的读音,而 "curses" 的发音类似于英文中的 "curses"。因此,它的发音类似于 "en-curses"。)
基本语法:通用选项 common options:(这个选项来设置dialog box的背景,颜色和标题等)[--title <title>] 指定将在对话框的上方显示的标题字符串
通用选项:
[ --backtitle ] 背景的标题
[--title ] 标题
[--stdout ] 改为正常输出流,可以使用变量获dialog命令的执行结果,dialog的默认输出流为2>
[--insecure ] 不安全的,显示星号(可以看到密码位数)
[--begin y x ] 窗体左上角处于屏幕的位置 例:--begin 4 10
[--colors ] 文本的颜色:0-7,1表示红色 ;\Z开始 ;\Zn结束
[--defaultno ] 默认为no yesno标签,对于yesno窗体类型,光标默认在no标签上
[--default-item string ] 默认条目,menu窗体类型中使用
[--nocancel ] 取消cancel键
[ --nook ] 取消ok键
[ --no-shadow ] 取消阴影
[ --ok-label string ] OK标签上不显示OK,而显示你输入的文本信息
[ --exit-label string ] 可以添加一个exit的标签
[ --timeout secs ] 超时时间间隔,秒
[ --extra-button ] 多添加一个按钮
[ --extra-labrl string ] 新增按钮上显示的内容,那这个按钮的功能这需要自己实现?用不来
部 件 描 述
----------------------------------------------------------------
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
widget是部件名, parameters定义了部件窗口的大小以及部件需要的文本。每个dialog部件都提供了两种形式的输出:
①使用STDERR
②使用退出状态码
可以通过dialog命令的退出状态码来确定用户选择的按钮。如果选择了Yes或OK按钮,dialog命令会返回退出状态码0。如果选择了Cancel或No按钮,dialog命令会返回退出状态码1。可以用标准的$?变量来确定dialog部件中具体选择了哪个按钮。
如果部件返回了数据,比如菜单选择,那么dialog命令会将数据发送到STDERR。可以用标准的bash shell方法来将STDERR输出重定向到另一个文件或文件描述符中。
dialog --inputbox "Enter your age:" 10 20 2>age.txt
一些其他的选项描述:
--add-widget 继续下个对话框,直到按下Esc或Cancel按钮
--aspect ratio 指定窗口宽度和高度的宽高比
--backtitle title 指定显示在屏幕顶部背景上的标题
--begin x y 指定窗口左上角的起始位置
--cancel-label label 指定Cancel按钮的替代标签
--clear 用默认的对话背景色来清空屏幕内容
--colors 在对话文本中嵌入ANSI色彩编码
--cr-wrap 在对话文本中允许使用换行符并强制换行
--create-rc file 将示例配置文件的内容复制到指定的file文件中(1)
--defaultno 将yes/no对话框的默认答案设为No
--default-item string 设定复选列表、表单或菜单对话中的默认项
--exit-label label 指定Exit按钮的替代标签
--extra-button 在OK按钮和Cancel按钮之间显示一个额外按钮
--extra-label label 指定额外按钮的替代标签
--help 显示dialog命令的帮助信息
--help-button 在OK按钮和Cancel按钮后显示一个Help按钮
--help-label label 指定Help按钮的替代标签
--help-status 当选定Help按钮后,在帮助信息后写入多选列表、单选列表或表单信息
--ignore 忽略dialog不能识别的选项
--input-fd fd 指定STDIN之外的另一个文件描述符
--insecure 在password部件中键入内容时显示星号
--item-help 为多选列表、单选列表或菜单中的每个标号在屏幕的底部添加一个帮助栏
--keep-window 不要清除屏幕上显示过的部件
--max-input size 指定输入的最大字符串长度。默认为2048
--nocancel 隐藏Cancel按钮
--no-collapse 不要将对话文本中的制表符转换成空格
--no-kill 将tailboxbg对话放到后台,并禁止该进程的SIGHUP信号
--no-label label 为No按钮指定替代标签
--no-shadow 不要显示对话窗口的阴影效果
--ok-label label 指定OK按钮的替代标签
--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秒后退出并返回错误代码
--title title 指定对话窗口的标题
--trim 从对话文本中删除前导空格和换行符
--visit-items 修改对话窗口中制表符的停留位置,使其包括选项列表
--yes-label label 为Yes按钮指定替代标签
实例:
msgbox部件(消息框)
msgbox部件是对话框中最常见的类型。它会在窗口中显示一条简单的消息,直到用户单击OK按钮后才消失。使用msgbox部件时要用下面的格式。
dialog --msgbox text height width
如果想在窗口顶部放一个标题,也可以用 --title参数,后接作为标题的文本。
# dialog --title "标题" --msgbox "这是文本内容~" 10 25
yesno部件(yesno框)
yesno部件进一步扩展了msgbox部件的功能,允许用户对窗口中显示的问题选择yes或no。它会在窗口底部生成两个按钮:一个是Yes,一个是No。用户可以用鼠标、制表符键或者键盘方向键来切换按钮。要选择按钮的话,用户可以按下空格键或者回车键。
如果用户选择了No按钮,退出状态码是1;如果选择了Yes按钮,退出状态码就是0。
# dialog --title "标题" --yesno "yes还是no?" 10 25;echo $?
选择no退出状态码是1:
选择yes退出状态码是0:
inputbox部件(输入文本框)
inputbox部件为用户提供了一个简单的文本框区域来输入文本字符串。 dialog命令会将文本字符串的值发给STDERR。你必须重定向STDERR来获取用户输入。
inputbox提供了两个按钮: OK和Cancel。如果选择了OK按钮,命令的退出状态码就是0;反之,退出状态码就会是1。
# dialog --inputbox "Enter your age:" 10 25 2>age.txt;echo $?
# cat age.txt
21
还可以直接在前面加一个参数--stdout,直接改为正常输出流,可以使用变量获dialog命令的执行结果:
# dialog --stdout --inputbox "Enter your age:" 10 25 >age1.txt;echo $?
# cat age1.txt
23
textbox部件(文本框)
textbox部件是在窗口中显示大量信息的极佳办法。它会生成一个滚动窗口来显示由参数所指定的文件中的文本。
# dialog --textbox /etc/passwd 15 45
menu部件(菜单框)
# dialog --menu "Sys Admin Menu" 20 30 10 1 "Display disk space" 2 "Display users" 3 "Display memory usage" 4 "Exit" 2> test.txt
fselect部件(文件选框)
fselect部件在处理文件名时非常方便。不用强制用户键入文件名,你就可以用fselect部件来浏览文件的位置并选择文件。
fselect选项后的第一个参数是窗口中使用的起始目录位置。 fselect部件窗口由左侧的目录列表、右侧的文件列表。
# dialog --title "Select a file" --fselect $HOME/ 10 50 2>file.txt
passwordbox部件(密码框)
格式: dialog --passwordbox text height width [init]
# dialog --title "Password" --passwordbox "Please give a password for the new user:" 10 35
这样我们的密码就暴露出来了,是不是很不安全,所以通常我们会加上一个安全选项
--insecure将每个字符用*来显示出来
# dialog --title "Password" --insecure --passwordbox "Please give a password for the new user:" 10 30
checklist部件(复选框)
格式:dialog --checklist "Test" height width menu-height tag1 item1 tag2 item2 …
例子:
# dialog --stdout --backtitle "Checklist" --checklist "Test" 20 50 10 Memory Memory_Size 1 Dsik Disk_Size 2
calendar部件(显示日历)
格式:dialog --calendar "Date" height width day month year
例子:
# dialog --title "Calendar" --calendar "Date" 5 50 #显示当前日期
# dialog --title "Calendar" --calendar "Date" 5 50 1 2 2013 #显示指定日期
gauge部件(进度框架)
格式:dialog --gauge text height width [<percent>]
例子:
#dialog --title "installation pro" --gauge "installation" 10 30 10 #固定进度显示
#for i in {1..100} ;do echo $i;done | dialog --title "installation pro" --gauge "installation" 10 30 #实时动度进度
编辑一个gauge.sh 的脚本,内容如下:
#!/bin/bash # 指定脚本使用的解释器为 Bash
declare -i PERCENT=0 #定义一个整型变量 PERCENT 并初始化为 0
( #开始一个子 shell
for I in /etc/*;do #遍历 /etc 目录下的所有文件
if [ $PERCENT -le 100 ];then #如果进度条未达到 100%,则执行以下命令
cp -r $I /tmp/test 2> /dev/null#将当前文件复制到 `/tmp/test` 目录中,忽略错误信息
echo "XXX" #输出分隔符
echo "Copy the file $I ..." #输出正在复制的文件名
echo "XXX" #输出分隔符
echo $PERCENT #输出当前进度百分比
fi
let PERCENT+=1 # 将进度百分比加 1
sleep 0.1 #等待 0.1 秒
done #结束循环
) | dialog --title "coping" --gauge "starting to copy files..." 6 50 0
# ) 结束子 shell
# | 将子 shell 的输出传递给下一个命令
#显示进度条对话框,标题为 "coping",提示信息为 "starting to copy files...",大小为 6 行 50 列,初始进度为 0
❀管道文件和文件描述符❀
在Bash中,管道文件和文件描述符是两个非常重要的概念,它们在很多情况下都会被用到。
管道文件:管道文件(也称为命名管道或FIFO)是一种特殊类型的文件,它在文件系统中有一个名称,但不占用任何磁盘空间。管道文件通常用于进程间通信,一个进程可以向管道文件中写入数据,而另一个进程则可以从管道文件中读取数据。这种通信方式是单向的,数据只能从写入端流向读取端。在Bash中,你可以使用mkfifo命令来创建一个管道文件。 例如,你可以创建一个管道文件,然后在一个后台进程中读取这个文件的内容,并将内容显示在一个dialog的gauge组件中,从而创建一个动态更新的进度条。这种方式在需要在脚本中显示进度信息时非常有用。
文件描述符:文件描述符是一个用于引用打开的文件或者管道的整数。在Bash中,每个进程都有三个默认的文件描述符:标准输入(0),标准输出(1)和标准错误(2)。你可以使用重定向操作符(>,>>,<,2>等)来改变这些文件描述符的指向。 例如,你可以使用command > file来将命令的输出重定向到一个文件,或者使用command 2> file来将命令的错误输出重定向到一个文件。这种方式在需要记录命令的输出或者错误信息时非常有用。 另外,你还可以使用exec命令来创建新的文件描述符,或者改变现有文件描述符的指向。例如,exec 3> file会创建一个新的文件描述符3,并将它指向文件file。这种方式在需要同时操作多个文件或者管道时非常有用。
总的来说,管道文件和文件描述符是Bash中进行进程间通信和输入/输出重定向的重要工具。理解它们的工作原理和使用方法,可以帮助你编写更加强大和灵活的脚本。
#!/bin/bash
mkfifo /tmp/my_pipe #创建一个管道文件
cat /tmp/my_pipe & #在后台启动一个进程,从管道文件中读取数据并打印
echo "Hello, World!" > /tmp/my_pipe #在主进程中向管道文件写入数据
rm /tmp/my_pipe #删除管道文件
在这个示例中,我们首先创建了一个管道文件/tmp/my_pipe。然后,我们在后台启动了一个进程,这个进程从管道文件中读取数据并打印。最后,我们在主进程中向管道文件写入数据。
#!/bin/bash
exec 3> /tmp/my_file #打开一个新的文件描述符并将其指向一个文件
echo "Hello, World!" >&3 #使用新的文件描述符写入数据
exec 3>&- #关闭文件描述符
在这个示例中,我们首先使用exec命令打开了一个新的文件描述符3,并将其指向一个文件/tmp/my_file。然后,我们使用新的文件描述符写入数据。最后,我们关闭了文件描述符。
这些示例展示了如何在bash脚本中使用管道文件和文件描述符进行进程间通信和输入/输出重定向。
假设你正在编写一个脚本,这个脚本需要在后台运行一个耗时的任务(例如,下载一个大文件),并在前台显示一个进度条。你可以使用一个管道文件来实现这个功能:
#!/bin/bash
mkfifo /tmp/progress_pipe #创建一个管道文件
dialog --gauge "Downloading file..." 10 70 < /tmp/progress_pipe & #在后台启动一个进程,从管道文件中读取进度信息并更新进度条
wget --progress=dot -O /dev/null http://example.com/bigfile 2>&1 | #
awk '/%/{print $6}' > /tmp/progress_pipe
rm /tmp/progress_pipe #删除管道文件
在这个示例中,我们首先创建了一个管道文件/tmp/progress_pipe。然后,我们在后台启动了一个进程,这个进程从管道文件中读取进度信息并更新dialog的gauge组件。最后,我们在主进程中启动了wget命令来下载一个大文件,并将wget的进度信息写入管道文件。
使用文件描述符进行错误日志记录:
假设你正在编写一个脚本,这个脚本需要执行一系列命令,并将所有命令的错误输出记录到一个日志文件。你可以使用一个文件描述符来实现这个功能:
#!/bin/bash
exec 3> /tmp/error.log #打开一个新的文件描述符并将其指向日志文件
#执行一系列命令,并将错误输出重定向到文件描述符3
command1 2>&3
command2 2>&3
command3 2>&3
exec 3>&- #关闭文件描述符
在这个示例中,我们首先使用exec命令打开了一个新的文件描述符3,并将其指向一个日志文件/tmp/error.log。然后,我们执行了一系列命令,并将这些命令的错误输出重定向到文件描述符3。最后,我们关闭了文件描述符。
❀$?的含义❀
在shell脚本中,$?是一个特殊的变量,它保存了上一个命令的退出状态码。当一个命令成功执行时,它的退出状态码为0,否则为非零值。if语句可以使用$?来判断上一个命令是否成功执行。
因此,if语句中的$? -eq 0表示判断上一个命令的退出状态码是否为0,如果是,则执行if语句中的代码块,否则跳过if语句中的代码块。
举个例子,假设我们执行了一个命令ls /tmp,如果该命令成功执行,则$?的值为0,如果失败,则$?的值为非零值。因此,我们可以使用以下if语句来判断该命令是否成功执行:
if [ $? -eq 0 ];
then
echo "ls /tmp executed successfully"
else
echo "ls /tmp failed to execute"
fi
form部件(表单)
格式:dialog --form text height width formheight [ label y x item y x flen ilen ] ...其中 flen 表示field length,定义了:选定字段中显示的长度 ilen 表示 input-length, 定义了:在外地输入的数据允许的长度 使用up/down(或ctrl/ N,ctrl/ P)在使用领域之间移动。使用tab键在窗口之间切换。
例子:
# dialog --title "Add a user" --form "Please input the infomation of new user:" 12 40 4 "Username:" 1 1 "" 1 15 15 0 "Full name:" 2 1 "" 2 15 15 0 "Home Dir:" 3 1 "" 3 15 15 0 "Shell:" 4 1 "" 4 15 15 0
1)dialog启动时会先去检查是否设置了DIALOGRC环境变量,该变量会保存配置文件名信息。如果未设置该变量或未找到该文件,它会将$HOME/.dialogrc作为配置文件。如果这个文件还不存在的话,就尝试查找编译时指定的GLOBALRC文件,也就是/etc/dialogrc。如果这个文件也不存在的话,就用编译时的默认值。
2)--backtitle选项是为脚本中的菜单创建公共标题的简便办法。如果你为每个对话窗口都指定了该选项,那么它在你的应用中就会保持一致,这样会让脚本看起来更专业。
综合应用示例
#!/bin/bash
yesno() {
dialog --title "First screen" --backtitle "Test Program" --clear --yesno \
"Start this test program or not ? \nThis decesion have to make by you. " 16 51
# yes is 0, no is 1 , esc is 255
result=$?
if [ $result -eq 1 ] ; then
exit 1;
elif [ $result -eq 255 ]; then
exit 255;
fi
username
}
username() {
cat /dev/null >/tmp/test.username
dialog --title "Second screen" --backtitle "Test Program" --clear --inputbox \
"Please input your username (default: hello) " 16 51 "hello" 2>/tmp/test.username
result=$?
if [ $result -eq 1 ] ; then
yesno
elif [ $result -eq 255 ]; then
exit 255;
fi
password
}
password() {
cat /dev/null >/tmp/test.password
dialog --insecure --title "Third screen" --backtitle "Test Program" --clear --passwordbox \
"Please input your password (default: 123456) " 16 51 "123456" 2>/tmp/test.password
result=$?
if [ $result -eq 1 ] ; then
username
elif [ $result -eq 255 ]; then
exit 255;
fi
occupation
}
occupation() {
cat /dev/null >/tmp/test.occupation
dialog --title "Forth screen" --backtitle "Test Program" --clear --menu \
"Please choose your occupation: (default: IT)" 16 51 3 \
IT "The worst occupation" \
CEO "The best occupation" \
Teacher "Not the best or worst" 2>/tmp/test.occupation
result=$?
if [ $result -eq 1 ] ; then
password
elif [ $result -eq 255 ]; then
exit 255;
fi
finish
}
finish() {
dialog --title "Fifth screen" --backtitle "Test Program" --clear --msgbox \
"Congratulations! The test program has finished!\n Username: $(cat /tmp/test.username)\n Password: $(cat /tmp/test.password)\n Occupation: $(cat /tmp/test.occupation)" 16 51
result=$?
if [ $result -eq 1 ] ; then
occupation
elif [ $result -eq 255 ]; then
exit 255;
fi
}
yesno