免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3420 | 回复: 0
打印 上一主题 下一主题

system-config-kickstart源码阅读(一)开局篇 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-11-02 11:55 |只看该作者 |倒序浏览

                之所以选择system-config-kickstart,是因为一直都熟悉这个工具,明白其功能,但不明白其用python是如何实现的,对于python在linux的系统管理方面的作为,最为精辟的论述莫过于《Python for Unix and Linux System
Administration》中第266页中如下内容:
Red Hat is doing a whole slew of things with Python as a company and as an operating system.
从系统管理配置工具到大名鼎鼎的anaconda再到现在的虚拟化管理甚至是集群、存储的管理工具,哪一个不是python写的?
当然,在系统中用python做工具的不止redhat,ubuntu也有不少工具,gentoo,arch等等不一而论,之所以选择redhat的工具,是因为其服务器的领头地位。
如上便是我记录学习历程的理由。
其网址是http://fedoraproject.org/wiki/SystemConfig/Tools,可以下载其正在开发中的版本。下载后,其文件有:
/data/lee/tmp/python/redhat_system_tools/system-config-kickstart $ tree .
.
|-- AUTHORS  //作者
|-- COPYING   //软件版权所有、及协议
|-- Makefile   //make编译配置文件
|-- doc      //文档目录
|   |-- docbook.css
|   |-- figs
|   |   |-- ksconfig-auth.png
|   |   |-- ksconfig-basic.png
|   |   |-- ksconfig-bootloader.png
|   |   |-- ksconfig-confirm.png
|   |   |-- ksconfig-firewall.png
|   |   |-- ksconfig-install.png
|   |   |-- ksconfig-network.png
|   |   |-- ksconfig-part-options.png
|   |   |-- ksconfig-partitions.png
|   |   |-- ksconfig-pkgs.png
|   |   |-- ksconfig-postscript.png
|   |   |-- ksconfig-prescript.png
|   |   |-- ksconfig-raid-device.png
|   |   |-- ksconfig-raid-new.png
|   |   |-- ksconfig-xconfig-general.png
|   |   |-- ksconfig-xconfig-monitor.png
|   |   |-- ksconfig-xconfig-videocard.png
|   |   `-- rhlogo.png
|   |-- index.html
|   |-- intro.html
|   |-- legalnotice.html
|   |-- rhdocs-man.css
|   |-- stylesheet-images
|   |   |-- caution.png
|   |   |-- important.png
|   |   |-- note.png
|   |   |-- tip.png
|   |   `-- warning.png
|   |-- system-config-kickstart-auth.html
|   |-- system-config-kickstart-basic.html
|   |-- system-config-kickstart-bootloader.html
|   |-- system-config-kickstart-bugzilla.html
|   |-- system-config-kickstart-firewall.html
|   |-- system-config-kickstart-install.html
|   |-- system-config-kickstart-interpreter.html
|   |-- system-config-kickstart-network.html
|   |-- system-config-kickstart-partitions.html
|   |-- system-config-kickstart-pkgs.html
|   |-- system-config-kickstart-postinstall-examples.html
|   |-- system-config-kickstart-postinstall.html
|   |-- system-config-kickstart-prescript.html
|   |-- system-config-kickstart-savefile.html
|   |-- system-config-kickstart-xconfig-monitor.html
|   |-- system-config-kickstart-xconfig-videocard.html
|   `-- system-config-kickstart-xconfig.html
|-- man   //在线文档man目录
|   |-- Makefile
|   |-- en
|   |   `-- system-config-kickstart.8
|   `-- ja
|       `-- system-config-kickstart.8
|-- pixmaps  //logo
|   `-- system-config-kickstart.png
|-- po  //存放GNUtext的翻译文件
|   |-- Makefile
|   |-- ar.mo
|   |-- ar.po
|   |-- as.mo
|   |-- as.po
|   |-- bg.mo
|   |-- bg.po
|   |-- bn.mo
|   |-- bn.po
|   |-- bn_IN.mo
|   |-- bn_IN.po
|   |-- bs.mo
|   |-- bs.po
|   |-- ca.mo
|   |-- ca.po
|   |-- cs.mo
|   |-- cs.po
|   |-- cy.mo
|   |-- cy.po
|   |-- da.mo
|   |-- da.po
|   |-- de.mo
|   |-- de.po
|   |-- el.mo
|   |-- el.po
|   |-- en_GB.mo
|   |-- en_GB.po
|   |-- es.mo
|   |-- es.po
|   |-- et.mo
|   |-- et.po
|   |-- fa.mo
|   |-- fa.po
|   |-- fi.mo
|   |-- fi.po
|   |-- fr.mo
|   |-- fr.po
|   |-- gu.mo
|   |-- gu.po
|   |-- he.mo
|   |-- he.po
|   |-- hi.mo
|   |-- hi.po
|   |-- hr.mo
|   |-- hr.po
|   |-- hu.mo
|   |-- hu.po
|   |-- hy.mo
|   |-- hy.po
|   |-- id.mo
|   |-- id.po
|   |-- is.mo
|   |-- is.po
|   |-- it.mo
|   |-- it.po
|   |-- ja.mo
|   |-- ja.po
|   |-- ka.mo
|   |-- ka.po
|   |-- kn.mo
|   |-- kn.po
|   |-- ko.mo
|   |-- ko.po
|   |-- ku.mo
|   |-- ku.po
|   |-- lo.mo
|   |-- lo.po
|   |-- mk.mo
|   |-- mk.po
|   |-- ml.mo
|   |-- ml.po
|   |-- mr.mo
|   |-- mr.po
|   |-- ms.mo
|   |-- ms.po
|   |-- my.mo
|   |-- my.po
|   |-- nb.mo
|   |-- nb.po
|   |-- nl.mo
|   |-- nl.po
|   |-- or.mo
|   |-- or.po
|   |-- pa.mo
|   |-- pa.po
|   |-- pl.mo
|   |-- pl.po
|   |-- pt.mo
|   |-- pt.po
|   |-- pt_BR.mo
|   |-- pt_BR.po
|   |-- ru.mo
|   |-- ru.po
|   |-- si.mo
|   |-- si.po
|   |-- sk.mo
|   |-- sk.po
|   |-- sl.mo
|   |-- sl.po
|   |-- sq.mo
|   |-- sq.po
|   |-- sr.mo
|   |-- sr.po
|   |-- sr@latin.mo
|   |-- sr@latin.po
|   |-- sv.mo
|   |-- sv.po
|   |-- system-config-kickstart.pot
|   |-- ta.mo
|   |-- ta.po
|   |-- te.mo
|   |-- te.po
|   |-- tmp
|   |   `-- system-config-kickstart.glade.h
|   |-- tr.mo
|   |-- tr.po
|   |-- uk.mo
|   |-- uk.po
|   |-- ur.mo
|   |-- ur.po
|   |-- vi.mo
|   |-- vi.po
|   |-- zh_CN.mo
|   |-- zh_CN.po
|   |-- zh_TW.mo
|   `-- zh_TW.po
|-- src   //源文件,这是重点要分析的。
|   |-- #raidOptionsWindow.py#|   |-- auth.py|   |-- auth.pyc|   |-- basic.py|   |-- basic.pyc|   |-- bootloader.py|   |-- bootloader.pyc|   |-- firewall.py|   |-- firewall.pyc|   |-- hardwareLists.py|   |-- hardwareLists.pyc|   |-- install.py|   |-- install.pyc|   |-- kickstartGui.py|   |-- kickstartGui.pyc|   |-- network.py|   |-- network.pyc|   |-- packages.py|   |-- packages.pyc|   |-- partEntry.py|   |-- partEntry.pyc|   |-- partWindow.py|   |-- partWindow.pyc|   |-- partition.py|   |-- partition.pyc|   |-- profileSystem.py|   |-- profileSystem.pyc|   |-- raidOptionsWindow.py|   |-- raidOptionsWindow.pyc|   |-- raidWindow.py|   |-- raidWindow.pyc|   |-- savedialog.py|   |-- savedialog.pyc|   |-- savefile.py|   |-- savefile.pyc|   |-- scripts.py|   |-- scripts.pyc|   |-- system-config-kickstart|   |-- system-config-kickstart.glade|   |-- system-config-kickstart.gladep|   |-- xconfig.py|   `-- xconfig.pyc
|-- system-config-kickstart.desktop.in  //gnome或kde的启动器
`-- system-config-kickstart.spec    //rpm包的spec文件
共有10 directories, 221 files。而我们管不了那么多,只有一个src对我们有用。至于文件则是一个都不会放过。
除去pyc模块文件,也就不到20个文件,先看我分析的流程图:

因为简单,所以清晰!结构一目了然。废话我就不多说了。现在进入正题,即开始分析python代码之system-config-kickstart文件,因为没有带后缀,emacs会认为它是一个bash脚本,所以不会有语法高亮显示:
其实此文件出去注释也没有多少行,分析起来是比较容易的(红色部分是我标出):
#!/usr/bin/python2      //linux脚本的首句,告诉解释器用什么,告诉file这是个什么文件,无它。
#
# Chris Lumens
# Brent Fox
# Tammy Fox
#
# Copyright (C) 2000-2008 Red Hat, Inc.
#
# This copyrighted material is made available to anyone wishing to use, modify,
# copy, or redistribute it subject to the terms and conditions of the GNU
# General Public License v.2 or, at your option, any later version.  This
# program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY expressed or implied, including the implied warranties of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  Any Red Hat
# trademarks that are incorporated in the source code or documentation are not
# subject to the GNU General Public License and may only be used or replicated
# with the express permission of Red Hat, Inc.
//以上是redhat的作者以及版权申明,此软件是遵循GPL。
import getopt   //引入模块getopt,ibm developworks 有篇文章就是将它如何构建强大的Unix命令行工具的。
import signal    //引入python关于unix的信号处理
import sys, os  //sys和os模块
from rhpl.exception import installExceptionHandler  // a userfriendly exception handling
sys.path.append("/usr/share/system-config-kickstart")  //给python追加环境变量。
##
## I18N
##
import gettext              //python对GNUtext的实现
gettext.textdomain("system-config-kickstart")
_ = lambda x: gettext.ldgettext("system-config-kickstart", x)  //python对函数式编程最简单的应用(此处会有专节出现)
def useCliMode(value):  //定义命令行使用的函数
    from pykickstart.version import makeVersion    ///usr/lib/python2.5/site-package/pykickstart目录下所有的文件,至于这行仅实现了调用一针对特定系统的版本号。
    import profileSystem   //导入profileSystem模块/usr/share/profileSystem,以下会分析。
    ksHandler = makeVersion()  //获得版本信息
    profileSystem = profileSystem.ProfileSystem(ksHandler)  //获得当前系统的安装配置信息,如语言、软件包、时区等
    try:   //加入异常处理
        fd = open(value, "w")  //试图生成用户指定的ks配置文件,value的来源是 下面绿色部分
    except IOError, e:   //失败后异常抛出,比如指定的目录,用户没有权限等。
        print _("The following error occurred while saving the "
                "kickstart config %s: %s") % (e.filename, e.strerror)
        return
    fd.write(ksHandler.__str__())  //写入指定文件
    fd.close()  //关闭文件描述符。
if __name__ == "__main__":  //python的入口函数,呵呵,个人理解的。
    signal.signal (signal.SIGINT, signal.SIG_DFL)   //捕捉信号,ctrl_C和perform the default function for the signal
    file = None   //定义file为空
    opts, file = getopt.getopt(sys.argv[1:], "g:h", ["generate=", "help", "display="])
               //定义什么可以为用户参数
    for (opt, value) in opts:
        if opt == "--display":
            os.environ["DISPLAY"] = value
        if opt == "--generate" or opt == "-g":
            useCliMode(value)
            sys.exit(1)//用此参数时,system-config-kickstart写完文件后退出,不再往下执行。
        if opt == "--help" or opt == "-h": //显示命令行帮助,以示友好。
            print _("""Usage: system-config-kickstart [--help] [--generate ] [--display=] []
    --help                  Print out this message
    --generate    Generate a kickstart file from the current machine and write
                            it to .  This option runs on the console, so it is
                            useful for servers that do not have X currently running.
        This option will cause the GUI to launch with the values from
                            the kickstart file already filled in.""")
            sys.exit(1)
    if file:
        file = file[0]   //将用户输入的将要保存的ks文件保存到一个序列中。
    try:    //用异常来导入模块,不失为一种好的方法。
        import kickstartGui         //配置界面的python文件
    except:
        print (_("Could not open display because no X server is running."))
        print (_("Try running 'system-config-kickstart --help' for a list of options."))
        sys.exit(0)
    installExceptionHandler("system-config-kickstart", "")        //rhel.exception的一个安转错误的函数。
    kickstartGui.kickstartGui(file) //调用kickstart配置界面类,以用户输入的文件名为参数。
好了,一个起始的文件就是这样,流程很清晰,在此就不再画出。我们再来看profileSystem.py文件:
(此处删去n行注释。。。)
import string
import sys
import os
sys.path.append("/usr/share/system-config-language")
import language_backend   //redhat另外一个关于语言管理的工具模块导入
import rhpl.keyboard as keyboard   
from pykickstart.constants import *
class ProfileSystem:
    def __init__(self, ksHandler):
        self.ks = ksHandler
        self.languageBackend = language_backend.LanguageBackend()
        self.getLang()    //定义getLang()方法
        self.getKeyboard()  //定义键盘
        self.getTimezone()  //定义时区
        self.getRootPassword()  //定义获得root用户密码方法
        self.getSELinux()     //定义获得 SELinux的设置
        self.getPackages()   //定义获得软件包
        self.ks.method(method="cdrom")  //默认安装介质
        self.ks.upgrade(upgrade=False)  //默认为非升级安装
        self.ks.zerombr(zerombr=True) //清空MBR
        self.ks.clearpart(type=CLEARPART_TYPE_LINUX)   //默认为删除所有linux分区。关于type的定义详见/usr/lib/python2.5/site-packages/pykickstart/constants.py
    def getLang(self):    //获取语言的设置
        default, langs = self.languageBackend.getInstalledLangs()//参照我的终端输出:>>> languageBackend = language_backend.LanguageBackend()>>> languageBackend.getInstalledLangs()('zh_CN', None)
        self.ks.lang(lang=default)
    def getKeyboard(self):   //redhat已经实现了一系列的底层硬件探测,很轻松就可以获得当前系统的键盘布局类型。
        kbd = keyboard.Keyboard()
        kbd.read()
        self.ks.keyboard(keyboard=kbd.get())
    def getTimezone(self):    //获得时区信息的方法实现。
        lines = open('/etc/sysconfig/clock', 'r').readlines()//呵呵,去找配置文件了。。。。
        for line in lines:
            if line[:4] == "ZONE":
                tag, zone = string.split(line, '=') //以等号为标识分割
        zone = string.replace(zone, '"', "") //注意此处的差别,将双引号替换为空
        zone = string.replace(zone, "'", "")//将单引号替换为空
        zone = string.strip(zone) //此是的zone便是配置文件中ZONE=""这句中没有标识出来的。
        self.ks.timezone(timezone=zone, isUtc=False)
    def getRootPassword(self):  //获得root用户密码
        if os.access('/etc/shadow', os.R_OK) == 1:
            line = open('/etc/shadow', 'r').readline()
            tokens = string.split(line, ":")
            self.ks.rootpw(isCrypted=True, password=tokens[1]) //[0]为用户。
        else:
            print "no access to /etc/shadow"
    def getSELinux(self):      //再显python的文本处理。
        lines = os.popen("/usr/sbin/getenforce").readlines()
        if lines[0].lower().startswith("disabled"):
            self.ks.selinux(selinux=SELINUX_DISABLED)
        elif lines[0].lower().startswith("permissive"):
            self.ks.selinux(selinux=SELINUX_PERMISSIVE)
        elif lines[0].lower().startswith("enforcing"):
            self.ks.selinux(selinux=SELINUX_ENFORCING)
    def getPackages(self):
        fd = os.popen("/bin/rpm -qa --queryformat \"%{NAME}\n\"") //搞笑吗? rpm -qa是最快的。
        packages = fd.readlines()
        fd.close
        packages.sort()//不忘了排序。。
        for package in packages:
            packages[packages.index(package)] = string.strip(package)
        self.ks.packages.add(packages)
就这样,两个文件分析完了,接下来我会分析kickstartGui文件,不过那些下一篇的事情了。
到底我有什么收获了呢?类、继承、方法、传参、函数、库、第三方库、语句、语法、功能、模块........但是我本身却是做不到的,为什么?
               
               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/6303/showart_1357340.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP