面向系统管理员的 Python
文档选项
未显示需要 JavaScript
的文档选项
级别: 中级
James Knowlton
(
[email=james@jamesknowlton.com?subject=%E9%9D%A2%E5%90%91%E7%B3%BB%E7%BB%9F%E7%AE%A1%E7%90%86%E5%91%98%E7%9A%84%20Python&cc=mmccrary@us.ibm.com]james@jamesknowlton.com[/email]
), 软件质量工程师, Freelance Writer
2007 年 10 月 08 日
采用 Python 来管理 UNIX® 系统,同时结合优秀的程序设计概念。Python 是一种易于学习的开放源代码脚本编写语言,它使得系统管理员能够更快速地完成工作。它还可以使工作变得充满乐趣。
引言
作
为一名系统管理员,您可能碰到过各种各样的挑战和问题。管理用户、磁盘空间、进程、设备和备份,可能让许多系统管理员绞尽脑汁,从而变得心情郁闷、甚至精
神错乱。Shell 脚本可以为此提供帮助,但是它们通常具有令人感到灰心的各种限制。在这种情况下,功能齐全的脚本编写语言(如
Python)可以将烦琐的任务变得更加容易、并且我敢说变得充满乐趣。
本文中的示例展示了不同的 Python 特性,您可以在实际应用中使用它们。如果您仔细地学习这些示例,那么您将能够了解 Python 的强大功能。
关于模块
模块是一个重要的 Python 概念。一般来说,模块 是您为了使用而进行导入的一项资源。这个过程就好比是从文件柜中取出一张纸,并将其放在桌面上,以便进行使用。您可以使用 import 命令导入模块,每个示例程序的最开始都出现了这个命令。其中提供了各种各样的模块,可用于数据库连接、网络编程、操作系统服务和许多其他有价值的领域。
使用 Python
为什么使用 Python?
之所以推荐 Python,是因为它具有许多特性:
- 它是免费的,是开放源代码。
- 它学习起来非常容易。许多用户认为,与其他脚本编写语言相比,它的语法更接近于英语。
- 它是非常成熟的。Python 已经出现很久了,这意味着它的代码是非常稳定的,可以通过许多模块来添加相应的功能,并且在 Web 上可以获得内容丰富的文档。
Python
是一种功能齐全的、可靠的编程语言,就这一点而论,它具有非常多的特性。学习这种语言可能不是一项非常容易的任务。然而请记住,许多 Python
特性(如 GUI 工具包)对系统管理员来说并没有太大的价值。这就是本文使用特定示例的原因:它们展示了您所需要掌握的相关技能,以便能够高效地编写
Python 脚本以完成系统管理工作。
有关示例的说明
- 每个示例都包括一个 try: 和一个 except:,以及外围代码块。这是基本错误处理的实现。Python 为处理所有类型的异常提供了广泛的支持,但是出于这些示例程序的目的,我尽量保持其简单。
- 这些示例运行于 Linux® 计算机中运行的 Python 2.5 之上,但是它们应该适用于任何 UNIX®/Linux 计算机。
- 您完全可以对这些脚本进行相应的修改。这是非常正确的做法!Python 脚本的本质是,可以很容易地对它们进行修改和自定义,而不需要重新编译代码。
示例 1:搜索文件,并以一种友好的格式显示权限
第一个示例程序(请参见
清单 1
)用于搜索匹配某种模式(基于用户的输入)的文件、以及为特定文件所分配的权限,并将结果显示在屏幕上。乍看上去,您可能认为这个程序并不比执行一个 find 命令能够完成更多的工作;然而,它能够以一种自定义的方式来显示结果,并且您用于显示这种增强的查找结果的选项是几乎不受任何限制的。这个示例向您介绍了如何使用一个系统命令,并使其更加完善(或者至少更具自定义性)。
该脚本主要执行下面三项任务:
从用户那里获得搜索模式。
- 执行搜索。
- 将结果呈现给用户。 在编写这个脚本时,您需要不断地问自己这个问题,“这个代码支持哪种任务?”向自己提这个问题,可以使得您更加关注于您的工作,并且提高效率。
清单 1. 搜索文件,并在结果中列出文件权限
import stat, sys, os, string, commands
#Getting search pattern from user and assigning it to a list
try:
#run a 'find' command and assign results to a variable
pattern = raw_input("Enter the file pattern to search for:\n")
commandString = "find " + patterncommandOutput = commands.getoutput(commandString)
findResults = string.split(commandOutput, "\n")
#output find results, along with permissions
print "Files:"
print commandOutput
print "================================"
for file in findResults:
mode=stat.S_IMODE(os.lstat(file)[stat.ST_MODE])
print "\nPermissions for file ", file, ":"
for level in "USR", "GRP", "OTH":
for perm in "R", "W", "X":
if mode %amp; getattr(stat,"S_I"+perm+level):
print level, " has ", perm, " permission"
else:
print level, " does NOT have ", perm, " permission"
except:
print "There was a problem - check the message above"
这个程序完成了下面的这些步骤:
- 请求用户输入一种搜索模式(第 7 行到第 9 行)。
- 显示所找到的文件的清单(第 12 行到第 14 行)。
- 使用 stat 模块,获得每个找到的文件的权限,并将它们显示在屏幕上(第 15 行到第 23 行)。
当这个程序运行时,输出结果应该与
清单 2
中所示类似。
清单 2. 第一个示例的输出
$ python example1.py
Enter the file pattern to search for:
j*.py
FILES FOUND FOR PATTERN j*.py :
jim.py
jim2.py
================================
Permissions for file jim.py :
USR R
USR W
USR X
GRP -
GRP -
GRP -
OTH -
OTH -
OTH -
Permissions for file jim2.py :
USR R
USR W
USR X
GRP R
GRP -
GRP X
OTH R
OTH -
OTH X
示例 2:基于菜单选择对 tar 存档文件执行操作
前一个示例提示用户输入要使用的搜索模式。另一种从用户那里获得信息的方式是通过命令行参数。
清单 3
中的程序说明了如何在 Python 中完成这项工作:这段代码接受一个 tar 文件的名称作为命令行参数,然后向用户提供几种选择。
这个示例还显示了一种新的解决问题的方法。第一个示例使用命令模块运行 find
命令,并捕获输出。这种方法可能比较笨拙,并且不是非常符合 Python 的习惯。这个示例使用 tarfile 模块打开 tar
文件,这样做的好处是,在操作文件时允许您使用 Python 的属性和方法。通过 Python
所提供的许多模块,您可以完成许多无法通过命令行完成的工作。
这是一个很好的示例,它说明了 Python 中菜单系统的实现。该程序将根据您的选择执行不同的操作:
- 如果您按 1,那么这个程序将提示您输入该存档文件中要提取到当前目录的文件名,然后提取该文件。
- 如果您按 2,那么这个程序将提示您输入文件名,然后显示该文件的信息。
- 如果您按 3,那么这个程序将列出该存档文件中所有的文件。
清单 3. 根据您的菜单选择对 tar 存档文件执行相应的操作
import tarfile, sys
try:
#open tarfile
tar = tarfile.open(sys.argv[1], "r:tar")
#present menu and get selection
selection = raw_input("Enter\n\
1 to extract a file\n\
2 to display information on a file in the archive\n\
3 to list all the files in the archive\n\n")
#perform actions based on selection above
if selection == "1":
filename = raw_input("enter the filename to extract: ")
tar.extract(filename)
elif selection == "2":
filename = raw_input("enter the filename to inspect: ")
for tarinfo in tar:
if tarinfo.name == filename:
print "\n\
Filename:\t\t", tarinfo.name, "\n\
Size:\t\t", tarinfo.size, "bytes\n\
elif selection == "3":
print tar.list(verbose=True)
except:
print "There was a problem running the program"
这个程序完成了下面的这些步骤:
- 打开 tar 文件(第 5 行)。
- 显示菜单,并获得用户的选择(第 8 行到第 11 行)。
- 如果您按 1(第 14 行到第 16 行),从该存档文件中提取一个文件。
- 如果您按 2(第 17 行到第 23 行),显示有关选择的文件的信息。
- 如果您按 3(第 24 行到第 25 行),显示该存档文件中所有文件的信息。
清单 4
中显示了输出结果。
清单 4. 第二个示例的用户菜单
$ python example2.py jimstar.tar
Enter
1 to extract a file
2 to display information on a file in the archive
3 to list all the files in the archive
示例 3:检查一个正在运行的进程,并以一种友好的格式显示其相关信息
对于系统管理员来说,最重要的任务之一是检查正在运行的进程。
清单 5
中的脚本为您提供了一些思路。这个程序利用 UNIX 的功能对某个命令生成的输出结果运行 grep 命令,这样做允许您自动缩小 Python 必须解析的数据的范围。
这个程序还使用了字符串模块。您需要了解这个模块,因为您将经常使用到它。
清单 5. 以友好的方式显示一个正在运行的进程的信息
import commands, os, string
program = raw_input("Enter the name of the program to check: ")
try:
#perform a ps command and assign results to a list
output = commands.getoutput("ps -f|grep " + program)
proginfo = string.split(output)
#display results
print "\n\
Full path:\t\t", proginfo[5], "\n\
Owner:\t\t\t", proginfo[0], "\n\
Process ID:\t\t", proginfo[1], "\n\
Parent process ID:\t", proginfo[2], "\n\
Time started:\t\t", proginfo[4]
except:
print "There was a problem with the program."
这个程序完成了下面的这些步骤:
- 获得要检查的进程的名称,并将其分配给一个变量(第 3 行)。
- 运行 ps 命令,并将结果分配给一个列表(第 7 行到第 8 行)。
- 使用英语术语显示有关进程的详细信息(第 11 行到第 16 行)。
其输出结果如
清单 6
所示。
清单 6. 第三个示例的输出
$ python example3.py
Enter the name of the program to check: xterm
Full path: /usr/bin/xterm
Owner: knowltoj
Process ID: 3220
Parent process ID: 4308
Time started: 16:51:46
示例 4:检查 userid 和密码以确保策略遵从性
对于任何系统管理员来说,安全管理都是其工作中非常关键的一部分。Python 使得这项工作更加简单,正如最后的示例所展示的。
清单 7
中的程序使用 pwd 模块来访问密码数据库。它检查 userid 和密码以确保安全策略遵从性(在这个示例中,userid 至少要有六个字符长,并且密码至少要有八个字符长)。
需要注意以下两点:
- 您必须拥有访问 /etc/passwd 的完全权限,这个程序才能正常工作。
- 如果您使用了 shadow 密码,那么这个脚本将无法工作(然而,Python 2.5 专门为完成这项工作提供了一个 spwd 模块)。
清单 7. 检查 userid 和密码以确保安全策略遵从性
import pwd
#initialize counters
erroruser = []
errorpass = []
#get password database
passwd_db = pwd.getpwall()
try:
#check each user and password for validity
for entry in passwd_db:
username = entry[0]
password = entry [1]
if len(username)
这个程序完成了下面的这些步骤:
- 初始化计数器列表(第 4 行到第 5 行)。
- 打开密码数据库,并将数据分配给一个列表(第 8 行)。
- 检查用户和密码的有效性(第 12 行到第 18 行)。
- 输出无效的用户和密码(第 21 行到第 26 行)。
输出结果如
清单 8
所示。
清单 8. 第四个示例的输出
$ python example4.py
The following users have an invalid userid (less than six characters):
Guest
The following users have invalid password(less than eight characters):
Guest
johnsmith
joewilson
suejones
脚本的其他用途
在系统管理的工作中,您可以采用许多不同的方式来使用 Python。您可以完成的主要任务之一是分析您的工作,确定需要重复执行的任务,并分析是否存在相应的 Python 模块以帮助您完成这些任务,当然,通常情况下是存在的。
Python 还可以在一些特定的领域为您提供很大的帮助,如下所示:
-
管理服务器:在一组服务器中为某个特定的应用程序检查修复程序级别,并自动地对它们进行更新。
-
日志记录:如果 syslog 中出现了特定类型的错误,则自动发送一封电子邮件。
-
网络连接:建立到服务器的 Telnet 连接,并监视连接的状态。
-
测试 Web 应用程序:使用可以免费获得的工具来模拟 Web 浏览器,并验证 Web 应用程序的功能和性能。
这些仅仅只是一些示例,我相信您可以添加一些自己的有价值的观点。
总结
因为 Python 是一种很容易学习的语言,它能够处理文件、进程、字符串和数值,并且提供了几乎各种各样的 Helper 模块,所以 Python 是一种非常适合系统管理员的脚本编写语言。对于任何系统管理员来说,它都是一种非常有价值的工具。