当前位置:Linux教程 - Linux - Webmin:Unix上的GUI管理工具(二)

Webmin:Unix上的GUI管理工具(二)

Webmin 技术内幕
金戈 ([email protected])
IBM软件工程师
2002 年 1 月

本文是对 Webmin介绍的第二部分,着重探讨 Webmin的技术内幕和如何编写 Webmin模块。文中首先介绍剖析了 Webmin内部结构,然后在 Webmin发行包基础上了裁减出了一个 Webmin的核心,最后介绍如何编写一个 Webmin模块。
剖析Webmin 的内部结构
解开 Webmin的安装包,可以发现Webmin 的目录的组成如下:

一组子目录,很显然这些子目录绝大多数都是一个Webmin 管理模块,而且可以看出Webmin完全由 perl实现;
一组perl脚本和几个CGI 脚本,这些脚本可以分为三类:
内置的HTTP服务器:它支持 CGI,Session 和SSL等功能。Miniserv.pl 和miniserv.pem实现了这个 HTTP服务器。它的配置文件通常是/etc/webmin/miniserv.conf, 它主要有如下几个重要参数: 参数及缺省值 说明
port=10000 设置 HTTP服务器监听的端口
root=/usr/libexec/webmin Web 文件的根目录
ssl=0 是否支持 SSL,如果设置为1 ,这个HTTP服务器将提供HTTPS 服务
session=1 是否支持 Session,如果设置为1 ,在访问Web服务之前必须先完成用户登录和认证,用户的登录和认证由 session_login.cgi实现
userfile=/etc/webmin/miniserv.users 存放 HTTP服务器的用户名和密码,changepass.pl 可以修改用户密码
keyfile=/etc/webmin/minserv.pem 存放 HTTP服务器的私钥和公钥证书



Webmin 核心:这部分包括Webmin核心库、 Webmin的首页和模块管理。Web-lib.pl 是Webmin的核心库,包含了 Webmin中主要的公用函数。Web-lib.pl 中会引用了一些CGI提供一些公用功能,这些 CGI包括: chooser.cgi 文件选择 Frame
date_chooser.cgi 日期选择 Frame
config.cgi 配置模块配置文件页面
config_save.cgi 保存配置
help.cgi 帮助页面
fastrpc.cgi 启动一个新进程以加快 rpc的调用
rpc.cgi 用于截获其他 Webmin服务器发来的Webmin 远过程调用
referer_save.cgi Redirect 到以前的URL
user_chooser.cgi 用户选择 Frame
switch_user.cgi 切换用户
switch_skill.cgi 改变当前 Webmin用户的Skill level
acl_security.cgi 配置全局 ACL选项


index.cgi 实现Webmin的首页,它将当前用户可以使用的管理模块按类别分为一个属性页显示。

Install-Module.pl 用于从命令行安装一个Webmin的管理模块。它调用了 copyconfig.pl和perlpath.pl 。

安装脚本:这些脚本用于安装配置Webmin 。Setup.pl是主要的配置脚本,它调用如下脚本:脚本 说明
newmods.pl 用于初始化一个新插入模块的配置文件
oschooser.pl 选择操作系统类型
copyconfig.pl 给管理模块复制配置文件
thirdparty.pl 检查已经安装的模块
perlpath.pl 当 perl的路径不是/usr/local/bin/perl 时,替换perl脚本中的#!/usr/local/bin/perl



裁减出Webmin 的核心
Webmin的开发目的是建立一个 Web界面的UNIX 系统管理工具,所以Webmin的发行版中不仅包含了 Webmin的工作核心,而且包含了大量的管理模块。而实际上裁减出一个 Webmin的核心也是件很有意义的事情,这主要体现在下面两个方面:

一般Webmin的自带的管理模块并不需要同时存在,能够需要什么模块时插入才是比较理想的做法
Webmin 核心为我们提供了一个支持认证和访问控制的Web 服务器和一套有效合理的开发小型Web应用的程序框架。


基于以上原因,笔者裁减出了一个 Webmin的核心并命名为webmin-platform 。和Webmin的发行版相比, Webmin-Platform具有如下特点:
短小精湛,webmin-platform的安装包只有 100多K, 缺省只包括Webmin配置和用户管理两个模块。 Webmin的其他模块可以顺利加入。
缺省情况下把Webmin的配置文件和 log文件都设置在安装目录,减少了对UNIX 系统的依赖性。

让笔者比较遗憾的是,目前 Webmin不支持Win32 平台,因此webmin-platform也不支持 Win32平台。有兴趣的读者,可以尝试把webmin-platform 移植到Windows平台。

Webmin模块
Webmin模块实际上是一个压缩过的 TAR包,你可以通过tar zxvf 命令解开任何一个Webmin模块包。一般 Webmin模块的结构如下所示: 目录或文件 说明
index.cgi 该模块的首页
config 缺省的配置文件
config.info 对配置文件中配置选项的说明
module.info 对模块的说明,包括模块名 (name)、模块描述(desc) 、类别(category)、依赖 (dependency)和模块版本(version )。
acl_security.pl 模块的访问控制
image/ 存放模块中用到的图片
lange/ 存放页面信息中的各种语言版本


Webmin模块中的 CGI脚本一般都具有相似的结构,下面将通过 Webmin技术文档中模板文件为例来说明这种结构:
#!/usr/bin/perl
#这是Webmin模块的一个模板
do ''../web-lib.pl'';
&init_config();
%access=&get_module_acl;
&ReadParse();
##检查访问控制(ACL)

##页眉
&header($text{''index_title''}, """", ""intro"", 1, 1, undef,
""Written byAuthorHome://page"");

##在这插入你的代码
##输出一个表格
print """",
""$text{''title''} "",
""$text{''prject1''} "",
"""";

##页脚
&footer(""/"", $text{''index''});

##模块中的子函数放在这里

### END of index.cgi ###.



这个模板文件结构很清晰,它依次由下面几部分组成:

Webmin 中的脚本文件必须包含Webmin根目录下的 web-lib.pl。web-lib.pl 是Webmin提供的支持库,所有的 Webmin的API 函数都在这个文件中定义。
模板文件首先调用init_config获取本模块的配置选项
接着需要调用get_module_acl获取访问控制表
调用ReadParse函数将 HTTP请求的参数编译到关联数组%in 中
下面就可以检查当前用户是否具有访问这个页面的权限了
以上是初始化工作,下面可以输出页面了。函数header 由Webmin提供,它打印出一个标准的 Webmin页眉
在输出你自己的页面内容后,可以调用footer 函数打印出Webmin标准的页脚。
下面几小节阐述编写Webmin模块涉及的几个主要问题。

这个模板文件结构很清晰,它依次由下面几部分组成:

Webmin 中的脚本文件必须包含Webmin根目录下的 web-lib.pl。web-lib.pl 是Webmin提供的支持库,所有的 Webmin的API 函数都在这个文件中定义。
模板文件首先调用init_config获取本模块的配置选项
接着需要调用get_module_acl获取访问控制表
调用ReadParse函数将 HTTP请求的参数编译到关联数组%in 中
下面就可以检查当前用户是否具有访问这个页面的权限了
以上是初始化工作,下面可以输出页面了。函数header 由Webmin提供,它打印出一个标准的 Webmin页眉
在输出你自己的页面内容后,可以调用footer 函数打印出Webmin标准的页脚。

下面几小节阐述编写Webmin模块涉及的几个主要问题。

统一的界面风格
Webmin要求形形色色的模块具有相同的界面风格和统一的色彩方案。为了达到这种效果,所有模块应该遵循如下规则:

所有支持image、table 和form的浏览器都能够正确显示管理页面。应该尽量避免使用 frame、DHTML 、JavaScript和Java 等和浏览器相关的特征;
所有产生HTML页面的CGI 程序都应该调有header生成页头。它会生成一个显示页面主题的图片,还可能会加入一些主要的连接。所有这些 CGI都应该保持字体类型、大小和风格的一致性;
应该使用$tb作为表格头的背景色,使用 $cb作为表格体的背景色。就像模板文件中的输出表格语句那样;
应该避免在Form中包含大量的输入控件,一些 UNIX的浏览器处理这样的Form 时会比较慢;

国际化支持
Webmin提供国际化支持。任何希望支持国际化的模块都应该包含子目录 lang。lang 目录中包含不同国家语言的系统消息翻译文件。这个文件中每一行包含一个消息的定义:

message_code=Message in this language

Webmin 根目录下的lang_list.txt包含了现在支持的语言和支持的编码格式。因为Webmin 的缺省语言是英语,所以消息翻译文件lang/en很特殊。当找不到某消息的某语言版本时会用它的英语版本代替。简体中文的翻译文件是 lang/zh_CN。

当使用在页面中使用国际化的消息时应该使用 Wembin定义的关联数组$text。如当前 Webmin使用简体中文,某模块的简体中文消息文件中包括:

index_title=我喜欢Webmin

那么 CGI程序中

print $text{"" index_title"" };

的输出是:

我喜欢Webmin

模块的配置
Webmin中的配置参数分为全局参数和模块参数。全局配置参数缺省放在 /etc/webmin/config中,模块配置参数缺省放在 /etc/webmin/$MODULENAME/config 中。在CGI中调用init_config 函数可以全局配置参数读入到关联数组%gconfig ,把模块配置参数读入到关联数组%config 中。

一个完整的模块应该具有 config.info文件,它定义了模块配置参数的信息。 Webmin根目录下的config.cgi 使用这个文件产生修改模块配置参数的页面。config.info 中每一行说明一个参数的信息:

config_name=description,type[,values]

config_name 定义了配置参数的描述,description 定义配置参数的说明,type定义配置参数值的类型, values定义配置参数的缺省值。

同一个模块可能在不同的 UNIX系统中具有不同的缺省配置。所以完整的模块还应该包含不同操作系统的缺省配置文件。这些配置文件的命名规则是:

config-osname-osversion
config-osname
config

Webmin目录下的 os_list.txt列出了当前Webmin 支持的UNIX系统

访问控制
Webmin支持基于模块的用户访问控制。 /etc/webmin/webmin.acl文件定义了 webmin用户可以访问的模块。如果想实现更小粒度的访问控制,可以使用 Webmin提供的基于模块操作的用户访问控制。在模块的配置目录下, Webmin会为每个用户生成一个访问控制文件,它通常被命名为 $username.acl (如root.acl) 。模块可以编写acl_security.pl 来操作这个文件。Webmin要求 acl_security.pl定义两个函数操作模块访问控制文件:

acl_security_form(acl) :该函数输出一个HTML的表格项。这个函数的输出提供给管理员修改某个用户对模块某个操作的访问权限。
acl_security_save(acl,input) :这个函数可以在保存管理员对访问权限修改前做些必要的操作。

如果没有 acl_security.pl,Webmin 会提供一个缺省的访问控制参数isconfig ,它指定一个用户是否拥有修改模块配置参数的权限。

如模板文件所示, CGI程序调用get_module_acl 把当前用户的访问权限读入一个关联数组。下面是在程序检测用户访问权限的例子:
#!/usr/local/bin/perl

require ''./foo-lib.pl'';

%access = &get_module_acl();

$access{''create''} || &error(""You are not allowed to create new foo users"");




其他问题
前几节阐述了编写 Webmin模块需要涉及的几个常见问题。下面是一些没有涉及到的问题:

文件加锁
活动日志
在线帮助
用户更新通知
界面主题

关于这些问题,请参阅 Webmin模块编写帮助。

常用函数
最后简单的列举编写 Webmin模块经常用到的函数和全局变量:


ReadParseMime:编译具有MIME 参数的HTTP请求参数
file_chooser_button:返回一个 JavaScript按钮,它允许用户选择一个 Webmin服务器上的一个文件
user_chooser_button:返回一个 JavaScript按钮,它允许用户选择一个 Webmin服务器上的系统用户
group_chooser_button:返回一个 JavaScript按钮,它允许用户选择一个 Webmin服务器上的用户组
$module_name:当前模块的名称
$module_config_directory:当前模块的配置文件目录

结语
可插入模块机制为 Webmin带来了极大的可扩展性,也使得用户可以方便的定制自己的管理模块。同时利用 Webmin平台构造一些小型的Web 应用也是个不错的选择。

参考资料

从http://www.webmin.com/webmin/download.html 下载最新版Webmin
从http://webmin.thirdpartymodules.com/ 下载第三方Webmin的管理模块
从http://www.webmin.com/webmin/index2.html 获取Webmin用户手册
从http://www.webmin.com/webmin/index3.html 获取Webmin的技术文档
在http://www.sourceforge.net 上查找第三方Webmin 的管理模块
笔者裁减的Webmin核心 webmin-platform-0.91.tgz

关于作者

金戈,IBM中国开发实验室软件工程师,2001年获中科院计算机科学硕士学位。主要研究方向是Linux、Java、软件工程和中间件技术。曾在《软件学报》等国家核心刊物上发表多篇论文,并主持开发过多个Linux和Java项目.