- 论坛徽章:
- 0
|
之所以选择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 |
|