[LinuxFocus-icon]
首页  |  站点地图  |  索引  |  搜索

新闻 | 过往期刊 | 链接 | 关于LF
This document is available in: English  Castellano  ChineseGB  Deutsch  Francais  Italiano  Nederlands  Russian  Turkce  

[Photo of the Authors]
by Katja and Guido Socher
<katja(at)linuxfocusorg, %20guido(at)linuxfocus.org>

About the authors:

Katja 是LinuxFocus的德国编辑. 她喜欢Tux, 电影, 摄影和大海. 这里是她的主页.

Guido 是一个长期linux爱好者. 他喜欢Linux因为它是由诚实和开放的人们设计的. 这就是我们称之为"开放源代码"的原因. 这儿是他的主页:linuxfocus.org/~guido.


目录:


 

(X)dialog: Talking shells

[Illustration]

摘要:

Xdialog和dialog是两种能使你的shell脚本具备图形用户界面(GUI)的工具.
你需要具备一些shell编程知识才能看懂这篇文章. 你可以看我们的Shell Programming这篇文章来学一些shell编程的基础知识.



 

简介

即使没有图形用户界面, UNIX shell本身就是一个非常有效的工作环境.
但某些原因使得有一个图形的对话框会使用户觉得更加直观. 比如一个程序的安装对话框. 你有大量的选项用来选择安装的特征,你可以选择目标目录....

 

使用 (X)dialog...

使用dialog和Xdialog你仅需要写一句短短的shell脚本就可以实现一个图形的化应用程序. Dialog是一个完全依赖于终端的程序,  Xdialog则是一个X11程序.
这儿有一个例子:
你可以输入(或 拷备/粘贴)下面这些语句到一个shell窗口里(xterm,konsole,...):

bash
Xdialog --yesno "Do you want to learn more about Xdialog?" 0 0;\
case $? in
0)
echo "Result: Yes chosen.";;
1)
echo "Result: No chosen.";;
255)
echo "ESC pressed.";;
esac

运行结果看起像这样:

[yes/no Xdialog]

如果你用dialog代替Xdialog (把上面的脚本里第二行的 X 去掉), 你就可以看到一个运行在xterm里的基于curses的程序,而不是一个分离的窗口里(下图). 在某些情况下, 这样的运行方式更适合一个仅需要在一个终端窗口运行的脚本. 除非你想让它运行在多台无法与你直接路由的主机上. 这种情况下dialog可以顺利运行而Xdialog则不能.


[yes/no dialog]

上面这些dialog/Xdialog的例子漂亮但毫无用处, 但它们说明了编写一个图形化的对话框是容易的. 还有许多有趣的对话框, 包括如日历,菜单,文件管理器,进度条,文本输入,消息框,密码框,.....你可以试着运行:

dialog --help
或者
Xdialog --help

来得到一个可用的对话框列表. Xdialog 拥有的对话框类型要比dialog少.
 

它是如何工作的

这些对话框是通过命令行来给定参数的.

dialog --yesno "text string" <height> <width>

你输入dialog 或 Xdialog 后, 必须给定对话框的名字和你想设置的一引起特殊参数.

"yesno"对话框有3个参数. <height>和<width>可以设置为0, 对话框会根据文本的长度自动调整宽度和高度. 结果将把对话框结束状态返回给脚本并保存在"$?"变量中. 如果还有更多的值需要返回,如被选项的名字, 则这个值会被返回到标准错误中(standard error). 标准错误通常只是被打印到屏幕上,但可以用"2>"来进行重定向.

一个非常简单而有效的解决办法.
 

真正的程序

现在,让我们来看一个实用的程序,Xdialog/dialog将比传统的shell脚本程序提供更多的便利: 一个让可以选择不同的ISP(Internet Service Providers)并且进行连接的菜单. 这个脚本需要2001年5月的文章 Using different ISPs for your Internet access 里提供的ppp-on/ppp-off脚本. 我们这个脚本叫做 pppdialout, 它会根据你是否在线显示出不同的菜单.
#!/bin/sh
#
# pppdialout
#
#DIALOG=Xdialog
DIALOG=dialog
#
# 你的默认ISP的名字:
defaultisp=maxnet
#
error()
{
echo "$1"
exit 2
}
help()
{
cat <<HELP
pppdialout -- select an ISP and dial out.
All available ISPs must have a config file in /etc/ppp/peers

pppdialout executes the ppp-on/ppp-off scripts as described
in http://linuxfocus.org/English/March2001/article192.shtml

pppdialout, copyright gpl, http://linuxfocus.org/English/November2002
HELP
exit 0
}

# 分析命令行参数:
while [ -n "$1" ]; do
case $1 in
-h) help;shift 1;; # function help is called
--) shift;break;; # end of options
-*) echo "error: no such option $1. -h for help";exit 1;;
*) break;;
esac
done

tempfile=/tmp/pppdialout.$$
trap "rm -f $tempfile" 1 2 5 15

# 检查是否已经连接internet
if /sbin/ifconfig | grep '^ppp' > /dev/null; then
# 我们已经在线
$DIALOG --title "go offline" --yesno "Click YES to \
terminate the ppp connection" 0 0
rval="$?"
clear
if [ "$rval" = "0" ]; then
echo "running /etc/ppp/scripts/ppp-off ..."
/etc/ppp/scripts/ppp-off
fi
else
# 没发现internet连接, 进行连接
# 从 /etc/ppp/peers 取得可用的ISP列表
for f in `ls /etc/ppp/peers`; do
if [ -f "/etc/ppp/peers/$f" ]; then
isplist="$isplist $f =="
fi
done
[ -z "$isplist" ]&&error "No isp def found in /etc/ppp/peers"
#
$DIALOG --default-item "$defaultisp" --title "pppdialout" \
--menu "Please select one of\
the following ISPs for dialout" 0 0 0 $isplist 2> $tempfile
rval="$?" # return status, isp name will be in $tempfile
clear
if [ "$rval" = "0" ]; then
isp=`cat $tempfile`
echo "running /etc/ppp/scripts/ppp-on $isp..."
/etc/ppp/scripts/ppp-on "$isp"
else
echo "Cancel..."
fi
rm -f $tempfile
fi
# pppdialout 结束
这个脚本是如何工作的:
开始,我们定义了一些函数:error和help, 下一步我们检查命令行参数,然后定义了一相临时文件(/tmp/pppdialout.$$). $$是当前进行的名字,它在每一个计算机中都是独立的. 陷井语句在程序被强制中断(如用户按下Ctrl+C)是执行并且删除我们定义的临时文件. 然后我检查我们是否已经在线(命令:/sbin/ifconfig | grep '^ppp'). 如果我们已经在线则打开一个对话框, 就像上面你所看到的那样, 询问用户是否要断连接. 如果我们不在线就打开一个菜单对话框. 我们从 /etc/ppp/peers (ls /etc/ppp/peers)中取得所有可用的ISPs. 菜单对话框的语法是:

dialog --menu "text" <height> <width> <menu height> <tag1> <description> ...

<height>, <width> 和<menu height> 被设置为0(自动调整,请看上面),然后是程序预定的语法格式的字符串(<tag1> <description>). 我们没有什么描述,就用了一些无意义的东西(==). 变量ipslist中的数据看起来像这样:

isp1 == isp2 == isp3 ==

用户的选择结果会被打印到标准错误. 命令"2> $tmpfile" 把这一结果写到我们的临时文件(tmpfile)里. 这个菜单对话框有cancel可选, 所以我们必须检查 $? (退出状态) 以确定那一个键被按下.

好啦, 理论已经足够. 结果看起来是这样:

... Xdialog产生的漂亮的GTK图形界面:

[pppdialout with xdialog]
[pppdialout with xdialog]

... 终端里基于 curses 的 dialog :

[pppdialout with dialog]
[pppdialout with dialog]

 

更多的程序More applications

我们还有另一个程序要献给你. 它是一个叫做mktgz的使用Xdialog的checklist对话框的程序. 基于平面终端的dialog没有checklist对话框,所以它只能使用Xdialog了. 你可以用 mktgz来建立 tar.gz 的压缩包. 用法:

mktgz yourpackage .

这个程序会显示当前目录(".")下的所有文件, 然后你可以选择哪些文件需要加入到yourpackage.tar.gz 包中. 你可以在这里下载这个程序(mktgz.txt). 我们不算一句一句的解释这个脚本,因为你已经能够读懂这个脚本了.

Xdialog 和 dialog 自带的一些例子在一个叫"samples"的目录里(Redhat 7.3 里在 /usr/share/doc/Xdialog-2.0.5/samples下). 请注意这些脚本不仅仅是做演示, 它们会真的去做一些事情.

 

总结

Xdialog 和 dialog 提供了大量的对话框类型. 所有这些类型的对话框并不适合所有类型的脚本. shell 本身就是一个"强大"的环境. 用tab键来自动补全目录比在图形用户界面中点击它们要快很多. 特别是管道和组合命令更是一个强大的工具. 就像这样:

grep -i "somestring" file.txt | sort | uniq | wc -l

(UNIX的shells要做同样的事则没有这么容易: 计算file.txt里包含"somestring"字串的行的数目)
可以用这种管道结构是因为这些命令全由命令行参数来控制. 换句话说: 它们不会停下来问用户它将如何继续运行.
虽然在程序中图形对话框非常有用, Xdialog 和 dialog 非常易于使用, 但必尽没有真正的图形化程序强大. 它们填补一纯ASCII shell脚本和全图形化程序这间的缺口.  

在那里下载 Xdialog 和 dialog?

首先可以找的地方是你的linux发行版光盘里. 也许已经安装到了你的计算机里(查询你的计算机: 如 rpm -qil Xdialog, dpkg -L Xdialog). Xdialog的主页是:
http://www.chez.com/godefroy/
dialog的主页是:
http://hightek.org/dialog/
你也可以这里下载 dialog/Xdialog.
 

参考资料

 

对这篇文章发表评论

每篇文章都有各自的反馈页面。在这个页面里,您可以提交评论,也可以查看其他读者的评论:
 反馈页面 

主页由LinuxFocus编辑组维护
© Katja and Guido Socher, FDL
LinuxFocus.org

点击这里向LinuxFocus报告错误或提出意见
翻译信息:
en --> -- : Katja and Guido Socher <katja(at)linuxfocusorg, %20guido(at)linuxfocus.org>
en --> zh: Walte YH <walteyh(at)sohu.com>

2003-04-06, generated by lfparser version 2.25