`
weiyinchao88
  • 浏览: 1176290 次
文章分类
社区版块
存档分类
最新评论

功能丰富的 Perl: 使用 Perl 自动化 UNIX 系统管理

 
阅读更多

文档选项
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- this content will be automatically generated across all content areas -->
<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

级别: 初级

Teodor Zlatanov (tzz@iglou.com), 程序员, Northern Light

2001 年 7 月 01 日

UNIX 系统管理总是一个棘手的问题,运用正确的工具会使这个问题变得容易。在这一部分中,Teodor 提出了关于使用 Perl 来简化和牢固系统管理的想法。在这种环境中,系统配置引擎 cfengine 是一个极其重要的工具。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

要完成本文中的练习,系统中必须安装了 Perl 5.6.0。操作系统最好是主流 UNIX 安装(Linux、Solaris、BSD)的最近版本(2000 或更新)。在较早版本的 Perl 和 UNIX 以及其它操作系统上也可以使用本文中的示例,但应当将可能的功能故障作为练习来解决。

UNIX 管理具有挑战性的一大原因是每个 UNIX 供应商认为标准是针对低能傻瓜。所以,即使是同一供应商的操作系统(SunOS 4.x 和 Solaris 5.x)也可以是根本不同。在某些情况下,甚至根本没有供应商。例如,Linux 没有单独的供应商(虽然 Red Hat 目前是最大的 Linux 分发版),每一个版本的 Linux 都有其独到之处。如果 POSIX 标准化做得正确,那么它是解决这一问题的正确方向上的一个步骤。遗憾的是,它只能保证系统管理所需功能的一个小的子集。

正如我经常所说:了解您的工具。如果试图仅用一种工具、语言、或方法做每件事情,可能是一场噩梦。要具有灵活性。

如果存在一个系统管理公理,那就是:两次过后,没有系统管理任务是有趣的。如果您发现正在重复做单调而枯燥的事,那么自动化它。当然,有时很难自动化,但应该至少考虑这个问题,并且权衡其优势及自动化所花费的时间。

cfengine 工具

如果您对自动化系统管理是认真的,那么应该了解 cfengine 工具。仅当您宁愿把时间都花在 vi 编辑器时,可以不去了解 cfengine

cfengine 是一种系统配置引擎。它获取配置脚本作为输入,然后根据这些脚本来行动。目前版本是 1.6.3(非常稳定的发行版),而且版本 2.0 也呼之欲出。有关 cfengine 开发的更多信息,请访问 cfengine 网站(请参阅本文后面的 参考资料)。

不一定要用 cfengine 提供您的所有东西,而且您不可能立刻需要所有东西。一开始时,您的 cfengine 配置文件应该很简单,并且随着发现更多东西希望自动化而增长。

来自 cfengine 命令参考大全,这里有其最值得注意的特性:

  • 可以监控和修改文件许可权和 ACL。例如,/etc/shadow 可以与 0400/root/sys 许可权保持一致,而且如果那些许可权发生变化,可以警告系统管理员或即刻纠正它们。
  • 根据相应 fstab 变化,可自动安装和卸载 NFS 文件。
  • 可以通过单一文件来管理子网掩码、DNS 配置、缺省路由和主网络接口;
  • 文件和目录可以递归复制至另一位置,要么本地复制,要么从远程服务器复制。
  • 可以编辑(这是一个 非常强大的特性,提供了正则表达式和全局查找/替换)、轮转(譬如,日志文件)或删除文件。
  • 可以链接文件(单一的和/或目录下的所有文件或与正则表达式匹配的文件)和整个目录。
  • 可以根据进程表中正则表达式的匹配来启动、杀死、重启进程或发送任意信号。
  • 可以运行任意命令。
  • 上述所有这些根据操作系统类型和修订版本、一天中的时间、任意用户定义的类、文件中文件、目录或数据的有无等等可以是有条件的。

即使用 Perl 可以做 cfengine 所做的所有事情,为什么要从头开始呢?例如,如果想用另一个词替换某个词,编辑文件可以是简单的一行程序。当开始允许系统的子类型、逻辑系统部分以及所有其它杂项因素时,这一行程序会变成 300 行。为什么不在 cfengine 中做呢?它产生 100 行可读的配置代码。

根据我自己的经验,因为可以从最小配置文件开始,然后随着时间流逝逐步地向 cfengine 添加一些东西,所以将 cfengine 介绍给站点是很容易的。没有人喜欢突然的变化,所有系统管理员更是如此(因为如果任何事出错,他们理所当然地会受到责难)。





回页首


配置文件管理

管理配置文件是艰苦的。可以通过考虑 cfengine 是否胜任该任务开始。遗憾的是, cfengine 的编辑是面向行的,所以它可能不太适合复杂的配置文件。但对于如 TCP 包装器配置文件 /etc/hosts.allow 那样的简单文件 cfengine 是最适合的。

通常,希望保留配置文件的多个版本。譬如,可能需要在 /etc/resolv.conf 中有两组 DNS 配置设置,一组是用于外部机器,另一组是用于内部机器。很自然,外部 DNS resolv.conf 可以进入称为 "external" 的目录,而内部 resolv.conf 可以进入相应的 "internal" 目录。让我们假定这两个目录都在一个全局 "spec" 目录下,该目录是配置文件的一种根目录。

下列代码会遍历 spec 目录,搜索适合于给定机器的文件名。它将从 /usr/local/spec 开始,然后往下,寻找与请求相匹配的文件。而且,它将检查每个目录的名称是否与属于某些机器的类相同。因此,如果我们请求 locate_global('resolv.conf', 'wonka') ,该函数将在 /usr/local/spec 目录下查找 resolv.conf 文件,该文件要么在根目录下,要么在该根目录的子目录下,它的名称应与 "wonka" 机器所属的类相匹配。所以,如果 "wonka" 属于 "chocolate" 类,并且如果有 /usr/local/spec/chocolate/resolv.conf 文件,那么 locate_global() 将返回 "/usr/local/spec/chocolate/resolv.conf"。

http://127.0.0.1:8080/developerworks/cn/linux/sdk/perl/culture-5/index.shtml locate_global() 找到与文件相匹配的多个版本(譬如,/usr/local/spec/chocolate/resolv.conf 和 /usr/local/spec/resolv.conf),则它会放弃。这里假设没有配置比有两个错误之一要好。还有,请注意,机器可以属于不止一个类。

可以构建这样的结构。譬如,

  • /usr/local/spec/external/chocolate/resolv.conf
  • /usr/local/spec/internal/chocolate/resolv.conf
  • /usr/local/spec/external/sugar/resolv.conf
  • /usr/local/spec/internal/sugar

将包含外部和内部 "chocolate" 以及 "sugar" 机器的文件。只需要正确地设置 your machine_belongs_to_class() 函数。

一旦 locate_global() 返回一个文件名,将它用 scp 或 rsync 复制至远程系统是相当简单的。请记住,总是要保持该文件的许可权和属性。scp 需要 "-p" 标志,rsync 需要 "-a" 标志。查阅想要使用的文件复制命令的文档。这样就有了一个统一的配置文件树。


清单 1:Spec 目录遍历
# {{{ locate_global: use spec directory to find a file matching the current class
sub locate_global($)
{
 # this code uses File::Find
 my $spec_dir = '/usr/local/spec';
 my $file = shift || return undef;      # file name sought
 my $machine = shift || return undef;   # machine name
 my @matches;
 my $find_sub =
  sub
  {
   print "found file 

文档选项
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- this content will be automatically generated across all content areas -->
<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

级别: 初级

Teodor Zlatanov (tzz@iglou.com), 程序员, Northern Light

2001 年 7 月 01 日

UNIX 系统管理总是一个棘手的问题,运用正确的工具会使这个问题变得容易。在这一部分中,Teodor 提出了关于使用 Perl 来简化和牢固系统管理的想法。在这种环境中,系统配置引擎 cfengine 是一个极其重要的工具。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

要完成本文中的练习,系统中必须安装了 Perl 5.6.0。操作系统最好是主流 UNIX 安装(Linux、Solaris、BSD)的最近版本(2000 或更新)。在较早版本的 Perl 和 UNIX 以及其它操作系统上也可以使用本文中的示例,但应当将可能的功能故障作为练习来解决。

UNIX 管理具有挑战性的一大原因是每个 UNIX 供应商认为标准是针对低能傻瓜。所以,即使是同一供应商的操作系统(SunOS 4.x 和 Solaris 5.x)也可以是根本不同。在某些情况下,甚至根本没有供应商。例如,Linux 没有单独的供应商(虽然 Red Hat 目前是最大的 Linux 分发版),每一个版本的 Linux 都有其独到之处。如果 POSIX 标准化做得正确,那么它是解决这一问题的正确方向上的一个步骤。遗憾的是,它只能保证系统管理所需功能的一个小的子集。

正如我经常所说:了解您的工具。如果试图仅用一种工具、语言、或方法做每件事情,可能是一场噩梦。要具有灵活性。

如果存在一个系统管理公理,那就是:两次过后,没有系统管理任务是有趣的。如果您发现正在重复做单调而枯燥的事,那么自动化它。当然,有时很难自动化,但应该至少考虑这个问题,并且权衡其优势及自动化所花费的时间。

cfengine 工具

如果您对自动化系统管理是认真的,那么应该了解 cfengine 工具。仅当您宁愿把时间都花在 vi 编辑器时,可以不去了解 cfengine

cfengine 是一种系统配置引擎。它获取配置脚本作为输入,然后根据这些脚本来行动。目前版本是 1.6.3(非常稳定的发行版),而且版本 2.0 也呼之欲出。有关 cfengine 开发的更多信息,请访问 cfengine 网站(请参阅本文后面的 参考资料)。

不一定要用 cfengine 提供您的所有东西,而且您不可能立刻需要所有东西。一开始时,您的 cfengine 配置文件应该很简单,并且随着发现更多东西希望自动化而增长。

来自 cfengine 命令参考大全,这里有其最值得注意的特性:

  • 可以监控和修改文件许可权和 ACL。例如,/etc/shadow 可以与 0400/root/sys 许可权保持一致,而且如果那些许可权发生变化,可以警告系统管理员或即刻纠正它们。
  • 根据相应 fstab 变化,可自动安装和卸载 NFS 文件。
  • 可以通过单一文件来管理子网掩码、DNS 配置、缺省路由和主网络接口;
  • 文件和目录可以递归复制至另一位置,要么本地复制,要么从远程服务器复制。
  • 可以编辑(这是一个 非常强大的特性,提供了正则表达式和全局查找/替换)、轮转(譬如,日志文件)或删除文件。
  • 可以链接文件(单一的和/或目录下的所有文件或与正则表达式匹配的文件)和整个目录。
  • 可以根据进程表中正则表达式的匹配来启动、杀死、重启进程或发送任意信号。
  • 可以运行任意命令。
  • 上述所有这些根据操作系统类型和修订版本、一天中的时间、任意用户定义的类、文件中文件、目录或数据的有无等等可以是有条件的。

即使用 Perl 可以做 cfengine 所做的所有事情,为什么要从头开始呢?例如,如果想用另一个词替换某个词,编辑文件可以是简单的一行程序。当开始允许系统的子类型、逻辑系统部分以及所有其它杂项因素时,这一行程序会变成 300 行。为什么不在 cfengine 中做呢?它产生 100 行可读的配置代码。

根据我自己的经验,因为可以从最小配置文件开始,然后随着时间流逝逐步地向 cfengine 添加一些东西,所以将 cfengine 介绍给站点是很容易的。没有人喜欢突然的变化,所有系统管理员更是如此(因为如果任何事出错,他们理所当然地会受到责难)。





回页首


配置文件管理

管理配置文件是艰苦的。可以通过考虑 cfengine 是否胜任该任务开始。遗憾的是, cfengine 的编辑是面向行的,所以它可能不太适合复杂的配置文件。但对于如 TCP 包装器配置文件 /etc/hosts.allow 那样的简单文件 cfengine 是最适合的。

通常,希望保留配置文件的多个版本。譬如,可能需要在 /etc/resolv.conf 中有两组 DNS 配置设置,一组是用于外部机器,另一组是用于内部机器。很自然,外部 DNS resolv.conf 可以进入称为 "external" 的目录,而内部 resolv.conf 可以进入相应的 "internal" 目录。让我们假定这两个目录都在一个全局 "spec" 目录下,该目录是配置文件的一种根目录。

下列代码会遍历 spec 目录,搜索适合于给定机器的文件名。它将从 /usr/local/spec 开始,然后往下,寻找与请求相匹配的文件。而且,它将检查每个目录的名称是否与属于某些机器的类相同。因此,如果我们请求 locate_global('resolv.conf', 'wonka') ,该函数将在 /usr/local/spec 目录下查找 resolv.conf 文件,该文件要么在根目录下,要么在该根目录的子目录下,它的名称应与 "wonka" 机器所属的类相匹配。所以,如果 "wonka" 属于 "chocolate" 类,并且如果有 /usr/local/spec/chocolate/resolv.conf 文件,那么 locate_global() 将返回 "/usr/local/spec/chocolate/resolv.conf"。

http://127.0.0.1:8080/developerworks/cn/linux/sdk/perl/culture-5/index.shtml locate_global() 找到与文件相匹配的多个版本(譬如,/usr/local/spec/chocolate/resolv.conf 和 /usr/local/spec/resolv.conf),则它会放弃。这里假设没有配置比有两个错误之一要好。还有,请注意,机器可以属于不止一个类。

可以构建这样的结构。譬如,

  • /usr/local/spec/external/chocolate/resolv.conf
  • /usr/local/spec/internal/chocolate/resolv.conf
  • /usr/local/spec/external/sugar/resolv.conf
  • /usr/local/spec/internal/sugar

将包含外部和内部 "chocolate" 以及 "sugar" 机器的文件。只需要正确地设置 your machine_belongs_to_class() 函数。

一旦 locate_global() 返回一个文件名,将它用 scp 或 rsync 复制至远程系统是相当简单的。请记住,总是要保持该文件的许可权和属性。scp 需要 "-p" 标志,rsync 需要 "-a" 标志。查阅想要使用的文件复制命令的文档。这样就有了一个统一的配置文件树。


清单 1:Spec 目录遍历
___FCKpd___0

一旦建立了这种 /usr/local/spec 结构的一个问题是:我们怎么知道 resolv.conf 应当进入 /etc?要么没有如这里所示的漂亮层次结构,改写它(譬如,用 "+" 替代 "/" - 一种危险的和有点丑陋的方法),要么在链接名与真实名之间保持单独的映射。譬如,"root-profile" 可以是 "~root/.profile" 的链接名。最后一种方法,也是我喜欢的方法,由于它平铺文件名并且消除了有隐藏文件名的问题。在一个目录结构下,每一样都是可见的和整洁的。当然,每次在将文件添加到列表时,需要多做一些工作。程序必须知道 "resolv.conf" 应该复制到远程系统的 "/etc/resolv.conf",并且 "dfstab" 应该进入 "/etc/dfs/dfstab"(共享 NFS 文件系统的 Solaris 文件)。

一旦设置完 spec 目录层次结构,现在让我们讨论可以做什么。如果想做,可以查找所有名为 Joe 的用户:


清单 2:查找所有 password 文件并用 grep 找出 Joe
grep Joe `find /usr/local/spec -name passwd`

或者可以使用工具,如 rep.pl(链接到 rep.pl),由 David Pitts 编写,来用另一个词替换每一个词:


清单 3:查找所有 host 文件并将 "wonka" 改成 "willy"
find /usr/local/spec -name hosts -exec rep.pl wonka willy {} /;

现在,如果愿意,可以用 Perl 编写清单 2 和 3; find2perl 就是为此编写的实用程序。虽然它非常简单,从开始只使用 find 。它真的是极好的实用程序,每个系统管理员都应该使用。更重要的是,编写这两个清单只花了我 5 分钟。了解如何使用 find2perl ,将它生成的代码存储在文件中,然后运行该文件,要花多长时间呢?自己试试看!





回页首


任务自动化

任务自动化是一个很泛的主题。我将本节仅限于非交互式 UNIX 命令的简单自动化。对于交互式命令的自动化,Expect 是当前可用的最好工具。应该要么了解它的语法,要么用 Perl Expect.pm 模块。可以从 CPAN 获取 Expect.pm ;请参阅 参考资料以了解更多详细信息。

利用 cfengine ,可以根据任意标准自动化几乎任何任务。但是,它的功能非常象 Makefile 功能,对变量的复杂操作是很难处理的。当发现需要运行这样的命令,该命令的参数来自于散列或通过单独的函数时,通常最好切换到 shell 脚本或 Perl。由于 Perl 的功能,其可能是较好的选择。虽然,不应该将 shell 脚本弃为替代来使用。有时,Perl 是不必要的,您只需要运行一些简单的命令。

自动添加用户是一个常见问题。可以编写自己的 adduser.pl 脚本, 或者用大多数现代 UNIX 系统提供的 adduser 程序。请确保使用的所有 UNIX 系统间语法是一致的,但不要尝试编写一个通用的 adduser 程序接口。它太难了,在您认为涵盖了所有 UNIX 变体后,迟早会有人要求 Win32 或 MacOS 版本。这不是仅仅用 Perl 就能解决的问题之一,除非您是非常有野心的。这里只是让脚本询问用户名、密码、主目录等等,并以 system() 调用来调用 adduser。


清单 4:用简单的脚本调用 adduser
#!/usr/bin/perl -w
use strict;
my %values;                             # will hold the values to fill in
# these are the known adduser switches
my %switches = ( home_dir => '-d', comment => '-c', group => '-G',
                 password => '-p', shell => '-s', uid => '-u');
# this location may vary on your system
my $command = '/usr/sbin/adduser ';
# for every switch, ask the user for a value
foreach my $setting (sort keys %switches, 'username')
{
 print "Enter the $setting or press Enter to skip: ";
 $values{$setting} = ;
 chomp $values{$setting};
 # if the user did not enter data, kill this setting
 delete $values{$setting} unless length $values{$setting};
}
die "Username must be provided" unless exists $values{username};
# for every filled-in value, add it with the right switch to the command
foreach my $setting (sort keys %switches)
{
 next unless exists $values{$setting};
 $command .= "$switches{$setting} $values{$setting} ";
}
# append the username itself
$command .= $values{username};
# important - let the user know what's going to happen
print "About to execute [$command]/n";
# return the exit status of the command
exit system($command);

用 Perl 来处理的另一个常见任务是监控和重新启动进程。通常,这是用 Proc::ProcessTable CPAN 模块进行的,它浏览整个进程表,并返回给用户带许多重要属性的进程列表。然而,在这里,我必须推荐 cfengine 。与快速的 Perl 工具相比,它提供了更好的进程监控和重新启动进程的选项。如果您想编写这样的工具,那么这只是在做别人做过的事情(而且 cfengine 已经偷了您的轮毂盖)。如果由于个人原因,不想用 cfengine ,考虑一下大多数现代 UNIX 系统中附带的 pgrep 和 pkill 实用程序。 pkill -HUP inetd 将用一条简洁的命令可以做四行或更多行 Perl 脚本所做的事情。这就是说,如果正在做的进程监控是很复杂或对时间敏感,那么应该明确用 Perl。

为了完整性缘故,这里是一个演示了如何使用 kill() Perl 函数的 Proc::ProcessTable 示例。"9" 作为参数,是最强的 kill() 参数,大体意味着“不管三七二十一,杀死进程再说”。不要以 root 运行这条命令,除非真想杀死 inetd 进程。


清单 5:遍历进程,然后杀死所有 inetd
use Proc::ProcessTable;
$t = new Proc::ProcessTable;
foreach $p (@{$t->table}) 
{
 # note that we will also kill "xinetd" and all processes
 # whose command line contains "inetd"
 kill 9, $p->pid if $p->cmndline =~ 'inetd';
}





回页首


结束语

UNIX 系统管理最让人失望的部分是 UNIX 供应商逃避标准而找到的各种方式。由于这种原因,当 Perl 单独应付 UNIX 系统中所有问题时,它是无能为力的。如果没有象 cfengine 这样的工具,象密码文件语法、共享文件系统以及跟踪日志等问题很快就变得无法管理。然而,还是存在一些希望;毕竟,我们只是查看了 Perl 可简化系统管理的一些方法。

Perl 与 cfengine 结合得很好。可以用 Perl 生成定制的 cfengine 配置,或者可以从 cfengine 运行 Perl 脚本。我用过这两者,发现集成不难。然而, cfengine 受过分简单的配置语言和缺乏数据结构影响。我将在有关 cfengine 的未来文章中展开这一问题。

如果选择实现的话,本文中介绍的集中化配置文件策略应当是非常实用的。在我的站点上现在已经使用了六个月,而且获得了巨大成功。如果将完整的层次结构检入一个如 CVS 那样的版本控制系统,您还将享受到版本化系统文件的好处,即可以回复到已检入版本控制系统的任一状态。



参考资料

/n"; push @matches, $File::Find::name if (

文档选项
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- this content will be automatically generated across all content areas -->
<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

级别: 初级

Teodor Zlatanov (tzz@iglou.com), 程序员, Northern Light

2001 年 7 月 01 日

UNIX 系统管理总是一个棘手的问题,运用正确的工具会使这个问题变得容易。在这一部分中,Teodor 提出了关于使用 Perl 来简化和牢固系统管理的想法。在这种环境中,系统配置引擎 cfengine 是一个极其重要的工具。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

要完成本文中的练习,系统中必须安装了 Perl 5.6.0。操作系统最好是主流 UNIX 安装(Linux、Solaris、BSD)的最近版本(2000 或更新)。在较早版本的 Perl 和 UNIX 以及其它操作系统上也可以使用本文中的示例,但应当将可能的功能故障作为练习来解决。

UNIX 管理具有挑战性的一大原因是每个 UNIX 供应商认为标准是针对低能傻瓜。所以,即使是同一供应商的操作系统(SunOS 4.x 和 Solaris 5.x)也可以是根本不同。在某些情况下,甚至根本没有供应商。例如,Linux 没有单独的供应商(虽然 Red Hat 目前是最大的 Linux 分发版),每一个版本的 Linux 都有其独到之处。如果 POSIX 标准化做得正确,那么它是解决这一问题的正确方向上的一个步骤。遗憾的是,它只能保证系统管理所需功能的一个小的子集。

正如我经常所说:了解您的工具。如果试图仅用一种工具、语言、或方法做每件事情,可能是一场噩梦。要具有灵活性。

如果存在一个系统管理公理,那就是:两次过后,没有系统管理任务是有趣的。如果您发现正在重复做单调而枯燥的事,那么自动化它。当然,有时很难自动化,但应该至少考虑这个问题,并且权衡其优势及自动化所花费的时间。

cfengine 工具

如果您对自动化系统管理是认真的,那么应该了解 cfengine 工具。仅当您宁愿把时间都花在 vi 编辑器时,可以不去了解 cfengine

cfengine 是一种系统配置引擎。它获取配置脚本作为输入,然后根据这些脚本来行动。目前版本是 1.6.3(非常稳定的发行版),而且版本 2.0 也呼之欲出。有关 cfengine 开发的更多信息,请访问 cfengine 网站(请参阅本文后面的 参考资料)。

不一定要用 cfengine 提供您的所有东西,而且您不可能立刻需要所有东西。一开始时,您的 cfengine 配置文件应该很简单,并且随着发现更多东西希望自动化而增长。

来自 cfengine 命令参考大全,这里有其最值得注意的特性:

  • 可以监控和修改文件许可权和 ACL。例如,/etc/shadow 可以与 0400/root/sys 许可权保持一致,而且如果那些许可权发生变化,可以警告系统管理员或即刻纠正它们。
  • 根据相应 fstab 变化,可自动安装和卸载 NFS 文件。
  • 可以通过单一文件来管理子网掩码、DNS 配置、缺省路由和主网络接口;
  • 文件和目录可以递归复制至另一位置,要么本地复制,要么从远程服务器复制。
  • 可以编辑(这是一个 非常强大的特性,提供了正则表达式和全局查找/替换)、轮转(譬如,日志文件)或删除文件。
  • 可以链接文件(单一的和/或目录下的所有文件或与正则表达式匹配的文件)和整个目录。
  • 可以根据进程表中正则表达式的匹配来启动、杀死、重启进程或发送任意信号。
  • 可以运行任意命令。
  • 上述所有这些根据操作系统类型和修订版本、一天中的时间、任意用户定义的类、文件中文件、目录或数据的有无等等可以是有条件的。

即使用 Perl 可以做 cfengine 所做的所有事情,为什么要从头开始呢?例如,如果想用另一个词替换某个词,编辑文件可以是简单的一行程序。当开始允许系统的子类型、逻辑系统部分以及所有其它杂项因素时,这一行程序会变成 300 行。为什么不在 cfengine 中做呢?它产生 100 行可读的配置代码。

根据我自己的经验,因为可以从最小配置文件开始,然后随着时间流逝逐步地向 cfengine 添加一些东西,所以将 cfengine 介绍给站点是很容易的。没有人喜欢突然的变化,所有系统管理员更是如此(因为如果任何事出错,他们理所当然地会受到责难)。





回页首


配置文件管理

管理配置文件是艰苦的。可以通过考虑 cfengine 是否胜任该任务开始。遗憾的是, cfengine 的编辑是面向行的,所以它可能不太适合复杂的配置文件。但对于如 TCP 包装器配置文件 /etc/hosts.allow 那样的简单文件 cfengine 是最适合的。

通常,希望保留配置文件的多个版本。譬如,可能需要在 /etc/resolv.conf 中有两组 DNS 配置设置,一组是用于外部机器,另一组是用于内部机器。很自然,外部 DNS resolv.conf 可以进入称为 "external" 的目录,而内部 resolv.conf 可以进入相应的 "internal" 目录。让我们假定这两个目录都在一个全局 "spec" 目录下,该目录是配置文件的一种根目录。

下列代码会遍历 spec 目录,搜索适合于给定机器的文件名。它将从 /usr/local/spec 开始,然后往下,寻找与请求相匹配的文件。而且,它将检查每个目录的名称是否与属于某些机器的类相同。因此,如果我们请求 locate_global('resolv.conf', 'wonka') ,该函数将在 /usr/local/spec 目录下查找 resolv.conf 文件,该文件要么在根目录下,要么在该根目录的子目录下,它的名称应与 "wonka" 机器所属的类相匹配。所以,如果 "wonka" 属于 "chocolate" 类,并且如果有 /usr/local/spec/chocolate/resolv.conf 文件,那么 locate_global() 将返回 "/usr/local/spec/chocolate/resolv.conf"。

http://127.0.0.1:8080/developerworks/cn/linux/sdk/perl/culture-5/index.shtml locate_global() 找到与文件相匹配的多个版本(譬如,/usr/local/spec/chocolate/resolv.conf 和 /usr/local/spec/resolv.conf),则它会放弃。这里假设没有配置比有两个错误之一要好。还有,请注意,机器可以属于不止一个类。

可以构建这样的结构。譬如,

  • /usr/local/spec/external/chocolate/resolv.conf
  • /usr/local/spec/internal/chocolate/resolv.conf
  • /usr/local/spec/external/sugar/resolv.conf
  • /usr/local/spec/internal/sugar

将包含外部和内部 "chocolate" 以及 "sugar" 机器的文件。只需要正确地设置 your machine_belongs_to_class() 函数。

一旦 locate_global() 返回一个文件名,将它用 scp 或 rsync 复制至远程系统是相当简单的。请记住,总是要保持该文件的许可权和属性。scp 需要 "-p" 标志,rsync 需要 "-a" 标志。查阅想要使用的文件复制命令的文档。这样就有了一个统一的配置文件树。


清单 1:Spec 目录遍历
___FCKpd___0

一旦建立了这种 /usr/local/spec 结构的一个问题是:我们怎么知道 resolv.conf 应当进入 /etc?要么没有如这里所示的漂亮层次结构,改写它(譬如,用 "+" 替代 "/" - 一种危险的和有点丑陋的方法),要么在链接名与真实名之间保持单独的映射。譬如,"root-profile" 可以是 "~root/.profile" 的链接名。最后一种方法,也是我喜欢的方法,由于它平铺文件名并且消除了有隐藏文件名的问题。在一个目录结构下,每一样都是可见的和整洁的。当然,每次在将文件添加到列表时,需要多做一些工作。程序必须知道 "resolv.conf" 应该复制到远程系统的 "/etc/resolv.conf",并且 "dfstab" 应该进入 "/etc/dfs/dfstab"(共享 NFS 文件系统的 Solaris 文件)。

一旦设置完 spec 目录层次结构,现在让我们讨论可以做什么。如果想做,可以查找所有名为 Joe 的用户:


清单 2:查找所有 password 文件并用 grep 找出 Joe
___FCKpd___1

或者可以使用工具,如 rep.pl(链接到 rep.pl),由 David Pitts 编写,来用另一个词替换每一个词:


清单 3:查找所有 host 文件并将 "wonka" 改成 "willy"
___FCKpd___2

现在,如果愿意,可以用 Perl 编写清单 2 和 3; find2perl 就是为此编写的实用程序。虽然它非常简单,从开始只使用 find 。它真的是极好的实用程序,每个系统管理员都应该使用。更重要的是,编写这两个清单只花了我 5 分钟。了解如何使用 find2perl ,将它生成的代码存储在文件中,然后运行该文件,要花多长时间呢?自己试试看!





回页首


任务自动化

任务自动化是一个很泛的主题。我将本节仅限于非交互式 UNIX 命令的简单自动化。对于交互式命令的自动化,Expect 是当前可用的最好工具。应该要么了解它的语法,要么用 Perl Expect.pm 模块。可以从 CPAN 获取 Expect.pm ;请参阅 参考资料以了解更多详细信息。

利用 cfengine ,可以根据任意标准自动化几乎任何任务。但是,它的功能非常象 Makefile 功能,对变量的复杂操作是很难处理的。当发现需要运行这样的命令,该命令的参数来自于散列或通过单独的函数时,通常最好切换到 shell 脚本或 Perl。由于 Perl 的功能,其可能是较好的选择。虽然,不应该将 shell 脚本弃为替代来使用。有时,Perl 是不必要的,您只需要运行一些简单的命令。

自动添加用户是一个常见问题。可以编写自己的 adduser.pl 脚本, 或者用大多数现代 UNIX 系统提供的 adduser 程序。请确保使用的所有 UNIX 系统间语法是一致的,但不要尝试编写一个通用的 adduser 程序接口。它太难了,在您认为涵盖了所有 UNIX 变体后,迟早会有人要求 Win32 或 MacOS 版本。这不是仅仅用 Perl 就能解决的问题之一,除非您是非常有野心的。这里只是让脚本询问用户名、密码、主目录等等,并以 system() 调用来调用 adduser。


清单 4:用简单的脚本调用 adduser
___FCKpd___3

用 Perl 来处理的另一个常见任务是监控和重新启动进程。通常,这是用 Proc::ProcessTable CPAN 模块进行的,它浏览整个进程表,并返回给用户带许多重要属性的进程列表。然而,在这里,我必须推荐 cfengine 。与快速的 Perl 工具相比,它提供了更好的进程监控和重新启动进程的选项。如果您想编写这样的工具,那么这只是在做别人做过的事情(而且 cfengine 已经偷了您的轮毂盖)。如果由于个人原因,不想用 cfengine ,考虑一下大多数现代 UNIX 系统中附带的 pgrep 和 pkill 实用程序。 pkill -HUP inetd 将用一条简洁的命令可以做四行或更多行 Perl 脚本所做的事情。这就是说,如果正在做的进程监控是很复杂或对时间敏感,那么应该明确用 Perl。

为了完整性缘故,这里是一个演示了如何使用 kill() Perl 函数的 Proc::ProcessTable 示例。"9" 作为参数,是最强的 kill() 参数,大体意味着“不管三七二十一,杀死进程再说”。不要以 root 运行这条命令,除非真想杀死 inetd 进程。


清单 5:遍历进程,然后杀死所有 inetd
___FCKpd___4





回页首


结束语

UNIX 系统管理最让人失望的部分是 UNIX 供应商逃避标准而找到的各种方式。由于这种原因,当 Perl 单独应付 UNIX 系统中所有问题时,它是无能为力的。如果没有象 cfengine 这样的工具,象密码文件语法、共享文件系统以及跟踪日志等问题很快就变得无法管理。然而,还是存在一些希望;毕竟,我们只是查看了 Perl 可简化系统管理的一些方法。

Perl 与 cfengine 结合得很好。可以用 Perl 生成定制的 cfengine 配置,或者可以从 cfengine 运行 Perl 脚本。我用过这两者,发现集成不难。然而, cfengine 受过分简单的配置语言和缺乏数据结构影响。我将在有关 cfengine 的未来文章中展开这一问题。

如果选择实现的话,本文中介绍的集中化配置文件策略应当是非常实用的。在我的站点上现在已经使用了六个月,而且获得了巨大成功。如果将完整的层次结构检入一个如 CVS 那样的版本控制系统,您还将享受到版本化系统文件的好处,即可以回复到已检入版本控制系统的任一状态。



参考资料

eq $file); # the machine_belongs_to_class sub returns true if a machine # belongs to a class; we stop traversing down otherwise $File::Find::prune = 1 unless machine_belongs_to_class($machine,

文档选项
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- this content will be automatically generated across all content areas -->
<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

级别: 初级

Teodor Zlatanov (tzz@iglou.com), 程序员, Northern Light

2001 年 7 月 01 日

UNIX 系统管理总是一个棘手的问题,运用正确的工具会使这个问题变得容易。在这一部分中,Teodor 提出了关于使用 Perl 来简化和牢固系统管理的想法。在这种环境中,系统配置引擎 cfengine 是一个极其重要的工具。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

要完成本文中的练习,系统中必须安装了 Perl 5.6.0。操作系统最好是主流 UNIX 安装(Linux、Solaris、BSD)的最近版本(2000 或更新)。在较早版本的 Perl 和 UNIX 以及其它操作系统上也可以使用本文中的示例,但应当将可能的功能故障作为练习来解决。

UNIX 管理具有挑战性的一大原因是每个 UNIX 供应商认为标准是针对低能傻瓜。所以,即使是同一供应商的操作系统(SunOS 4.x 和 Solaris 5.x)也可以是根本不同。在某些情况下,甚至根本没有供应商。例如,Linux 没有单独的供应商(虽然 Red Hat 目前是最大的 Linux 分发版),每一个版本的 Linux 都有其独到之处。如果 POSIX 标准化做得正确,那么它是解决这一问题的正确方向上的一个步骤。遗憾的是,它只能保证系统管理所需功能的一个小的子集。

正如我经常所说:了解您的工具。如果试图仅用一种工具、语言、或方法做每件事情,可能是一场噩梦。要具有灵活性。

如果存在一个系统管理公理,那就是:两次过后,没有系统管理任务是有趣的。如果您发现正在重复做单调而枯燥的事,那么自动化它。当然,有时很难自动化,但应该至少考虑这个问题,并且权衡其优势及自动化所花费的时间。

cfengine 工具

如果您对自动化系统管理是认真的,那么应该了解 cfengine 工具。仅当您宁愿把时间都花在 vi 编辑器时,可以不去了解 cfengine

cfengine 是一种系统配置引擎。它获取配置脚本作为输入,然后根据这些脚本来行动。目前版本是 1.6.3(非常稳定的发行版),而且版本 2.0 也呼之欲出。有关 cfengine 开发的更多信息,请访问 cfengine 网站(请参阅本文后面的 参考资料)。

不一定要用 cfengine 提供您的所有东西,而且您不可能立刻需要所有东西。一开始时,您的 cfengine 配置文件应该很简单,并且随着发现更多东西希望自动化而增长。

来自 cfengine 命令参考大全,这里有其最值得注意的特性:

  • 可以监控和修改文件许可权和 ACL。例如,/etc/shadow 可以与 0400/root/sys 许可权保持一致,而且如果那些许可权发生变化,可以警告系统管理员或即刻纠正它们。
  • 根据相应 fstab 变化,可自动安装和卸载 NFS 文件。
  • 可以通过单一文件来管理子网掩码、DNS 配置、缺省路由和主网络接口;
  • 文件和目录可以递归复制至另一位置,要么本地复制,要么从远程服务器复制。
  • 可以编辑(这是一个 非常强大的特性,提供了正则表达式和全局查找/替换)、轮转(譬如,日志文件)或删除文件。
  • 可以链接文件(单一的和/或目录下的所有文件或与正则表达式匹配的文件)和整个目录。
  • 可以根据进程表中正则表达式的匹配来启动、杀死、重启进程或发送任意信号。
  • 可以运行任意命令。
  • 上述所有这些根据操作系统类型和修订版本、一天中的时间、任意用户定义的类、文件中文件、目录或数据的有无等等可以是有条件的。

即使用 Perl 可以做 cfengine 所做的所有事情,为什么要从头开始呢?例如,如果想用另一个词替换某个词,编辑文件可以是简单的一行程序。当开始允许系统的子类型、逻辑系统部分以及所有其它杂项因素时,这一行程序会变成 300 行。为什么不在 cfengine 中做呢?它产生 100 行可读的配置代码。

根据我自己的经验,因为可以从最小配置文件开始,然后随着时间流逝逐步地向 cfengine 添加一些东西,所以将 cfengine 介绍给站点是很容易的。没有人喜欢突然的变化,所有系统管理员更是如此(因为如果任何事出错,他们理所当然地会受到责难)。





回页首


配置文件管理

管理配置文件是艰苦的。可以通过考虑 cfengine 是否胜任该任务开始。遗憾的是, cfengine 的编辑是面向行的,所以它可能不太适合复杂的配置文件。但对于如 TCP 包装器配置文件 /etc/hosts.allow 那样的简单文件 cfengine 是最适合的。

通常,希望保留配置文件的多个版本。譬如,可能需要在 /etc/resolv.conf 中有两组 DNS 配置设置,一组是用于外部机器,另一组是用于内部机器。很自然,外部 DNS resolv.conf 可以进入称为 "external" 的目录,而内部 resolv.conf 可以进入相应的 "internal" 目录。让我们假定这两个目录都在一个全局 "spec" 目录下,该目录是配置文件的一种根目录。

下列代码会遍历 spec 目录,搜索适合于给定机器的文件名。它将从 /usr/local/spec 开始,然后往下,寻找与请求相匹配的文件。而且,它将检查每个目录的名称是否与属于某些机器的类相同。因此,如果我们请求 locate_global('resolv.conf', 'wonka') ,该函数将在 /usr/local/spec 目录下查找 resolv.conf 文件,该文件要么在根目录下,要么在该根目录的子目录下,它的名称应与 "wonka" 机器所属的类相匹配。所以,如果 "wonka" 属于 "chocolate" 类,并且如果有 /usr/local/spec/chocolate/resolv.conf 文件,那么 locate_global() 将返回 "/usr/local/spec/chocolate/resolv.conf"。

http://127.0.0.1:8080/developerworks/cn/linux/sdk/perl/culture-5/index.shtml locate_global() 找到与文件相匹配的多个版本(譬如,/usr/local/spec/chocolate/resolv.conf 和 /usr/local/spec/resolv.conf),则它会放弃。这里假设没有配置比有两个错误之一要好。还有,请注意,机器可以属于不止一个类。

可以构建这样的结构。譬如,

  • /usr/local/spec/external/chocolate/resolv.conf
  • /usr/local/spec/internal/chocolate/resolv.conf
  • /usr/local/spec/external/sugar/resolv.conf
  • /usr/local/spec/internal/sugar

将包含外部和内部 "chocolate" 以及 "sugar" 机器的文件。只需要正确地设置 your machine_belongs_to_class() 函数。

一旦 locate_global() 返回一个文件名,将它用 scp 或 rsync 复制至远程系统是相当简单的。请记住,总是要保持该文件的许可权和属性。scp 需要 "-p" 标志,rsync 需要 "-a" 标志。查阅想要使用的文件复制命令的文档。这样就有了一个统一的配置文件树。


清单 1:Spec 目录遍历
___FCKpd___0

一旦建立了这种 /usr/local/spec 结构的一个问题是:我们怎么知道 resolv.conf 应当进入 /etc?要么没有如这里所示的漂亮层次结构,改写它(譬如,用 "+" 替代 "/" - 一种危险的和有点丑陋的方法),要么在链接名与真实名之间保持单独的映射。譬如,"root-profile" 可以是 "~root/.profile" 的链接名。最后一种方法,也是我喜欢的方法,由于它平铺文件名并且消除了有隐藏文件名的问题。在一个目录结构下,每一样都是可见的和整洁的。当然,每次在将文件添加到列表时,需要多做一些工作。程序必须知道 "resolv.conf" 应该复制到远程系统的 "/etc/resolv.conf",并且 "dfstab" 应该进入 "/etc/dfs/dfstab"(共享 NFS 文件系统的 Solaris 文件)。

一旦设置完 spec 目录层次结构,现在让我们讨论可以做什么。如果想做,可以查找所有名为 Joe 的用户:


清单 2:查找所有 password 文件并用 grep 找出 Joe
___FCKpd___1

或者可以使用工具,如 rep.pl(链接到 rep.pl),由 David Pitts 编写,来用另一个词替换每一个词:


清单 3:查找所有 host 文件并将 "wonka" 改成 "willy"
___FCKpd___2

现在,如果愿意,可以用 Perl 编写清单 2 和 3; find2perl 就是为此编写的实用程序。虽然它非常简单,从开始只使用 find 。它真的是极好的实用程序,每个系统管理员都应该使用。更重要的是,编写这两个清单只花了我 5 分钟。了解如何使用 find2perl ,将它生成的代码存储在文件中,然后运行该文件,要花多长时间呢?自己试试看!





回页首


任务自动化

任务自动化是一个很泛的主题。我将本节仅限于非交互式 UNIX 命令的简单自动化。对于交互式命令的自动化,Expect 是当前可用的最好工具。应该要么了解它的语法,要么用 Perl Expect.pm 模块。可以从 CPAN 获取 Expect.pm ;请参阅 参考资料以了解更多详细信息。

利用 cfengine ,可以根据任意标准自动化几乎任何任务。但是,它的功能非常象 Makefile 功能,对变量的复杂操作是很难处理的。当发现需要运行这样的命令,该命令的参数来自于散列或通过单独的函数时,通常最好切换到 shell 脚本或 Perl。由于 Perl 的功能,其可能是较好的选择。虽然,不应该将 shell 脚本弃为替代来使用。有时,Perl 是不必要的,您只需要运行一些简单的命令。

自动添加用户是一个常见问题。可以编写自己的 adduser.pl 脚本, 或者用大多数现代 UNIX 系统提供的 adduser 程序。请确保使用的所有 UNIX 系统间语法是一致的,但不要尝试编写一个通用的 adduser 程序接口。它太难了,在您认为涵盖了所有 UNIX 变体后,迟早会有人要求 Win32 或 MacOS 版本。这不是仅仅用 Perl 就能解决的问题之一,除非您是非常有野心的。这里只是让脚本询问用户名、密码、主目录等等,并以 system() 调用来调用 adduser。


清单 4:用简单的脚本调用 adduser
___FCKpd___3

用 Perl 来处理的另一个常见任务是监控和重新启动进程。通常,这是用 Proc::ProcessTable CPAN 模块进行的,它浏览整个进程表,并返回给用户带许多重要属性的进程列表。然而,在这里,我必须推荐 cfengine 。与快速的 Perl 工具相比,它提供了更好的进程监控和重新启动进程的选项。如果您想编写这样的工具,那么这只是在做别人做过的事情(而且 cfengine 已经偷了您的轮毂盖)。如果由于个人原因,不想用 cfengine ,考虑一下大多数现代 UNIX 系统中附带的 pgrep 和 pkill 实用程序。 pkill -HUP inetd 将用一条简洁的命令可以做四行或更多行 Perl 脚本所做的事情。这就是说,如果正在做的进程监控是很复杂或对时间敏感,那么应该明确用 Perl。

为了完整性缘故,这里是一个演示了如何使用 kill() Perl 函数的 Proc::ProcessTable 示例。"9" 作为参数,是最强的 kill() 参数,大体意味着“不管三七二十一,杀死进程再说”。不要以 root 运行这条命令,除非真想杀死 inetd 进程。


清单 5:遍历进程,然后杀死所有 inetd
___FCKpd___4





回页首


结束语

UNIX 系统管理最让人失望的部分是 UNIX 供应商逃避标准而找到的各种方式。由于这种原因,当 Perl 单独应付 UNIX 系统中所有问题时,它是无能为力的。如果没有象 cfengine 这样的工具,象密码文件语法、共享文件系统以及跟踪日志等问题很快就变得无法管理。然而,还是存在一些希望;毕竟,我们只是查看了 Perl 可简化系统管理的一些方法。

Perl 与 cfengine 结合得很好。可以用 Perl 生成定制的 cfengine 配置,或者可以从 cfengine 运行 Perl 脚本。我用过这两者,发现集成不难。然而, cfengine 受过分简单的配置语言和缺乏数据结构影响。我将在有关 cfengine 的未来文章中展开这一问题。

如果选择实现的话,本文中介绍的集中化配置文件策略应当是非常实用的。在我的站点上现在已经使用了六个月,而且获得了巨大成功。如果将完整的层次结构检入一个如 CVS 那样的版本控制系统,您还将享受到版本化系统文件的好处,即可以回复到已检入版本控制系统的任一状态。



参考资料

) ||

文档选项
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- this content will be automatically generated across all content areas -->
<!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

级别: 初级

Teodor Zlatanov (tzz@iglou.com), 程序员, Northern Light

2001 年 7 月 01 日

UNIX 系统管理总是一个棘手的问题,运用正确的工具会使这个问题变得容易。在这一部分中,Teodor 提出了关于使用 Perl 来简化和牢固系统管理的想法。在这种环境中,系统配置引擎 cfengine 是一个极其重要的工具。
<!--START RESERVED FOR FUTURE USE INCLUDE FILES--><!-- include java script once we verify teams wants to use this and it will work on dbcs and cyrillic characters --><!--END RESERVED FOR FUTURE USE INCLUDE FILES-->

要完成本文中的练习,系统中必须安装了 Perl 5.6.0。操作系统最好是主流 UNIX 安装(Linux、Solaris、BSD)的最近版本(2000 或更新)。在较早版本的 Perl 和 UNIX 以及其它操作系统上也可以使用本文中的示例,但应当将可能的功能故障作为练习来解决。

UNIX 管理具有挑战性的一大原因是每个 UNIX 供应商认为标准是针对低能傻瓜。所以,即使是同一供应商的操作系统(SunOS 4.x 和 Solaris 5.x)也可以是根本不同。在某些情况下,甚至根本没有供应商。例如,Linux 没有单独的供应商(虽然 Red Hat 目前是最大的 Linux 分发版),每一个版本的 Linux 都有其独到之处。如果 POSIX 标准化做得正确,那么它是解决这一问题的正确方向上的一个步骤。遗憾的是,它只能保证系统管理所需功能的一个小的子集。

正如我经常所说:了解您的工具。如果试图仅用一种工具、语言、或方法做每件事情,可能是一场噩梦。要具有灵活性。

如果存在一个系统管理公理,那就是:两次过后,没有系统管理任务是有趣的。如果您发现正在重复做单调而枯燥的事,那么自动化它。当然,有时很难自动化,但应该至少考虑这个问题,并且权衡其优势及自动化所花费的时间。

cfengine 工具

如果您对自动化系统管理是认真的,那么应该了解 cfengine 工具。仅当您宁愿把时间都花在 vi 编辑器时,可以不去了解 cfengine

cfengine 是一种系统配置引擎。它获取配置脚本作为输入,然后根据这些脚本来行动。目前版本是 1.6.3(非常稳定的发行版),而且版本 2.0 也呼之欲出。有关 cfengine 开发的更多信息,请访问 cfengine 网站(请参阅本文后面的 参考资料)。

不一定要用 cfengine 提供您的所有东西,而且您不可能立刻需要所有东西。一开始时,您的 cfengine 配置文件应该很简单,并且随着发现更多东西希望自动化而增长。

来自 cfengine 命令参考大全,这里有其最值得注意的特性:

  • 可以监控和修改文件许可权和 ACL。例如,/etc/shadow 可以与 0400/root/sys 许可权保持一致,而且如果那些许可权发生变化,可以警告系统管理员或即刻纠正它们。
  • 根据相应 fstab 变化,可自动安装和卸载 NFS 文件。
  • 可以通过单一文件来管理子网掩码、DNS 配置、缺省路由和主网络接口;
  • 文件和目录可以递归复制至另一位置,要么本地复制,要么从远程服务器复制。
  • 可以编辑(这是一个 非常强大的特性,提供了正则表达式和全局查找/替换)、轮转(譬如,日志文件)或删除文件。
  • 可以链接文件(单一的和/或目录下的所有文件或与正则表达式匹配的文件)和整个目录。
  • 可以根据进程表中正则表达式的匹配来启动、杀死、重启进程或发送任意信号。
  • 可以运行任意命令。
  • 上述所有这些根据操作系统类型和修订版本、一天中的时间、任意用户定义的类、文件中文件、目录或数据的有无等等可以是有条件的。

即使用 Perl 可以做 cfengine 所做的所有事情,为什么要从头开始呢?例如,如果想用另一个词替换某个词,编辑文件可以是简单的一行程序。当开始允许系统的子类型、逻辑系统部分以及所有其它杂项因素时,这一行程序会变成 300 行。为什么不在 cfengine 中做呢?它产生 100 行可读的配置代码。

根据我自己的经验,因为可以从最小配置文件开始,然后随着时间流逝逐步地向 cfengine 添加一些东西,所以将 cfengine 介绍给站点是很容易的。没有人喜欢突然的变化,所有系统管理员更是如此(因为如果任何事出错,他们理所当然地会受到责难)。





回页首


配置文件管理

管理配置文件是艰苦的。可以通过考虑 cfengine 是否胜任该任务开始。遗憾的是, cfengine 的编辑是面向行的,所以它可能不太适合复杂的配置文件。但对于如 TCP 包装器配置文件 /etc/hosts.allow 那样的简单文件 cfengine 是最适合的。

通常,希望保留配置文件的多个版本。譬如,可能需要在 /etc/resolv.conf 中有两组 DNS 配置设置,一组是用于外部机器,另一组是用于内部机器。很自然,外部 DNS resolv.conf 可以进入称为 "external" 的目录,而内部 resolv.conf 可以进入相应的 "internal" 目录。让我们假定这两个目录都在一个全局 "spec" 目录下,该目录是配置文件的一种根目录。

下列代码会遍历 spec 目录,搜索适合于给定机器的文件名。它将从 /usr/local/spec 开始,然后往下,寻找与请求相匹配的文件。而且,它将检查每个目录的名称是否与属于某些机器的类相同。因此,如果我们请求 locate_global('resolv.conf', 'wonka') ,该函数将在 /usr/local/spec 目录下查找 resolv.conf 文件,该文件要么在根目录下,要么在该根目录的子目录下,它的名称应与 "wonka" 机器所属的类相匹配。所以,如果 "wonka" 属于 "chocolate" 类,并且如果有 /usr/local/spec/chocolate/resolv.conf 文件,那么 locate_global() 将返回 "/usr/local/spec/chocolate/resolv.conf"。

http://127.0.0.1:8080/developerworks/cn/linux/sdk/perl/culture-5/index.shtml locate_global() 找到与文件相匹配的多个版本(譬如,/usr/local/spec/chocolate/resolv.conf 和 /usr/local/spec/resolv.conf),则它会放弃。这里假设没有配置比有两个错误之一要好。还有,请注意,机器可以属于不止一个类。

可以构建这样的结构。譬如,

  • /usr/local/spec/external/chocolate/resolv.conf
  • /usr/local/spec/internal/chocolate/resolv.conf
  • /usr/local/spec/external/sugar/resolv.conf
  • /usr/local/spec/internal/sugar

将包含外部和内部 "chocolate" 以及 "sugar" 机器的文件。只需要正确地设置 your machine_belongs_to_class() 函数。

一旦 locate_global() 返回一个文件名,将它用 scp 或 rsync 复制至远程系统是相当简单的。请记住,总是要保持该文件的许可权和属性。scp 需要 "-p" 标志,rsync 需要 "-a" 标志。查阅想要使用的文件复制命令的文档。这样就有了一个统一的配置文件树。


清单 1:Spec 目录遍历
___FCKpd___0

一旦建立了这种 /usr/local/spec 结构的一个问题是:我们怎么知道 resolv.conf 应当进入 /etc?要么没有如这里所示的漂亮层次结构,改写它(譬如,用 "+" 替代 "/" - 一种危险的和有点丑陋的方法),要么在链接名与真实名之间保持单独的映射。譬如,"root-profile" 可以是 "~root/.profile" 的链接名。最后一种方法,也是我喜欢的方法,由于它平铺文件名并且消除了有隐藏文件名的问题。在一个目录结构下,每一样都是可见的和整洁的。当然,每次在将文件添加到列表时,需要多做一些工作。程序必须知道 "resolv.conf" 应该复制到远程系统的 "/etc/resolv.conf",并且 "dfstab" 应该进入 "/etc/dfs/dfstab"(共享 NFS 文件系统的 Solaris 文件)。

一旦设置完 spec 目录层次结构,现在让我们讨论可以做什么。如果想做,可以查找所有名为 Joe 的用户:


清单 2:查找所有 password 文件并用 grep 找出 Joe
___FCKpd___1

或者可以使用工具,如 rep.pl(链接到 rep.pl),由 David Pitts 编写,来用另一个词替换每一个词:


清单 3:查找所有 host 文件并将 "wonka" 改成 "willy"
___FCKpd___2

现在,如果愿意,可以用 Perl 编写清单 2 和 3; find2perl 就是为此编写的实用程序。虽然它非常简单,从开始只使用 find 。它真的是极好的实用程序,每个系统管理员都应该使用。更重要的是,编写这两个清单只花了我 5 分钟。了解如何使用 find2perl ,将它生成的代码存储在文件中,然后运行该文件,要花多长时间呢?自己试试看!





回页首


任务自动化

任务自动化是一个很泛的主题。我将本节仅限于非交互式 UNIX 命令的简单自动化。对于交互式命令的自动化,Expect 是当前可用的最好工具。应该要么了解它的语法,要么用 Perl Expect.pm 模块。可以从 CPAN 获取 Expect.pm ;请参阅 参考资料以了解更多详细信息。

利用 cfengine ,可以根据任意标准自动化几乎任何任务。但是,它的功能非常象 Makefile 功能,对变量的复杂操作是很难处理的。当发现需要运行这样的命令,该命令的参数来自于散列或通过单独的函数时,通常最好切换到 shell 脚本或 Perl。由于 Perl 的功能,其可能是较好的选择。虽然,不应该将 shell 脚本弃为替代来使用。有时,Perl 是不必要的,您只需要运行一些简单的命令。

自动添加用户是一个常见问题。可以编写自己的 adduser.pl 脚本, 或者用大多数现代 UNIX 系统提供的 adduser 程序。请确保使用的所有 UNIX 系统间语法是一致的,但不要尝试编写一个通用的 adduser 程序接口。它太难了,在您认为涵盖了所有 UNIX 变体后,迟早会有人要求 Win32 或 MacOS 版本。这不是仅仅用 Perl 就能解决的问题之一,除非您是非常有野心的。这里只是让脚本询问用户名、密码、主目录等等,并以 system() 调用来调用 adduser。


清单 4:用简单的脚本调用 adduser
___FCKpd___3

用 Perl 来处理的另一个常见任务是监控和重新启动进程。通常,这是用 Proc::ProcessTable CPAN 模块进行的,它浏览整个进程表,并返回给用户带许多重要属性的进程列表。然而,在这里,我必须推荐 cfengine 。与快速的 Perl 工具相比,它提供了更好的进程监控和重新启动进程的选项。如果您想编写这样的工具,那么这只是在做别人做过的事情(而且 cfengine 已经偷了您的轮毂盖)。如果由于个人原因,不想用 cfengine ,考虑一下大多数现代 UNIX 系统中附带的 pgrep 和 pkill 实用程序。 pkill -HUP inetd 将用一条简洁的命令可以做四行或更多行 Perl 脚本所做的事情。这就是说,如果正在做的进程监控是很复杂或对时间敏感,那么应该明确用 Perl。

为了完整性缘故,这里是一个演示了如何使用 kill() Perl 函数的 Proc::ProcessTable 示例。"9" 作为参数,是最强的 kill() 参数,大体意味着“不管三七二十一,杀死进程再说”。不要以 root 运行这条命令,除非真想杀死 inetd 进程。


清单 5:遍历进程,然后杀死所有 inetd
___FCKpd___4





回页首


结束语

UNIX 系统管理最让人失望的部分是 UNIX 供应商逃避标准而找到的各种方式。由于这种原因,当 Perl 单独应付 UNIX 系统中所有问题时,它是无能为力的。如果没有象 cfengine 这样的工具,象密码文件语法、共享文件系统以及跟踪日志等问题很快就变得无法管理。然而,还是存在一些希望;毕竟,我们只是查看了 Perl 可简化系统管理的一些方法。

Perl 与 cfengine 结合得很好。可以用 Perl 生成定制的 cfengine 配置,或者可以从 cfengine 运行 Perl 脚本。我用过这两者,发现集成不难。然而, cfengine 受过分简单的配置语言和缺乏数据结构影响。我将在有关 cfengine 的未来文章中展开这一问题。

如果选择实现的话,本文中介绍的集中化配置文件策略应当是非常实用的。在我的站点上现在已经使用了六个月,而且获得了巨大成功。如果将完整的层次结构检入一个如 CVS 那样的版本控制系统,您还将享受到版本化系统文件的好处,即可以回复到已检入版本控制系统的任一状态。



参考资料

eq '.'; }; find($find_sub, $spec_dir); if (scalar @matches > 1) { print "More than one match for file $file,", "machine $machine found: @matches/n" ; return undef; } elsif (scalar @matches == 1) { return $matches[0]; # this is the right match } else { return undef; # no files found } } # }}}

一旦建立了这种 /usr/local/spec 结构的一个问题是:我们怎么知道 resolv.conf 应当进入 /etc?要么没有如这里所示的漂亮层次结构,改写它(譬如,用 "+" 替代 "/" - 一种危险的和有点丑陋的方法),要么在链接名与真实名之间保持单独的映射。譬如,"root-profile" 可以是 "~root/.profile" 的链接名。最后一种方法,也是我喜欢的方法,由于它平铺文件名并且消除了有隐藏文件名的问题。在一个目录结构下,每一样都是可见的和整洁的。当然,每次在将文件添加到列表时,需要多做一些工作。程序必须知道 "resolv.conf" 应该复制到远程系统的 "/etc/resolv.conf",并且 "dfstab" 应该进入 "/etc/dfs/dfstab"(共享 NFS 文件系统的 Solaris 文件)。

一旦设置完 spec 目录层次结构,现在让我们讨论可以做什么。如果想做,可以查找所有名为 Joe 的用户:


清单 2:查找所有 password 文件并用 grep 找出 Joe
___FCKpd___1

或者可以使用工具,如 rep.pl(链接到 rep.pl),由 David Pitts 编写,来用另一个词替换每一个词:


清单 3:查找所有 host 文件并将 "wonka" 改成 "willy"
___FCKpd___2

现在,如果愿意,可以用 Perl 编写清单 2 和 3; find2perl 就是为此编写的实用程序。虽然它非常简单,从开始只使用 find 。它真的是极好的实用程序,每个系统管理员都应该使用。更重要的是,编写这两个清单只花了我 5 分钟。了解如何使用 find2perl ,将它生成的代码存储在文件中,然后运行该文件,要花多长时间呢?自己试试看!





回页首


任务自动化

任务自动化是一个很泛的主题。我将本节仅限于非交互式 UNIX 命令的简单自动化。对于交互式命令的自动化,Expect 是当前可用的最好工具。应该要么了解它的语法,要么用 Perl Expect.pm 模块。可以从 CPAN 获取 Expect.pm ;请参阅 参考资料以了解更多详细信息。

利用 cfengine ,可以根据任意标准自动化几乎任何任务。但是,它的功能非常象 Makefile 功能,对变量的复杂操作是很难处理的。当发现需要运行这样的命令,该命令的参数来自于散列或通过单独的函数时,通常最好切换到 shell 脚本或 Perl。由于 Perl 的功能,其可能是较好的选择。虽然,不应该将 shell 脚本弃为替代来使用。有时,Perl 是不必要的,您只需要运行一些简单的命令。

自动添加用户是一个常见问题。可以编写自己的 adduser.pl 脚本, 或者用大多数现代 UNIX 系统提供的 adduser 程序。请确保使用的所有 UNIX 系统间语法是一致的,但不要尝试编写一个通用的 adduser 程序接口。它太难了,在您认为涵盖了所有 UNIX 变体后,迟早会有人要求 Win32 或 MacOS 版本。这不是仅仅用 Perl 就能解决的问题之一,除非您是非常有野心的。这里只是让脚本询问用户名、密码、主目录等等,并以 system() 调用来调用 adduser。


清单 4:用简单的脚本调用 adduser
___FCKpd___3

用 Perl 来处理的另一个常见任务是监控和重新启动进程。通常,这是用 Proc::ProcessTable CPAN 模块进行的,它浏览整个进程表,并返回给用户带许多重要属性的进程列表。然而,在这里,我必须推荐 cfengine 。与快速的 Perl 工具相比,它提供了更好的进程监控和重新启动进程的选项。如果您想编写这样的工具,那么这只是在做别人做过的事情(而且 cfengine 已经偷了您的轮毂盖)。如果由于个人原因,不想用 cfengine ,考虑一下大多数现代 UNIX 系统中附带的 pgrep 和 pkill 实用程序。 pkill -HUP inetd 将用一条简洁的命令可以做四行或更多行 Perl 脚本所做的事情。这就是说,如果正在做的进程监控是很复杂或对时间敏感,那么应该明确用 Perl。

为了完整性缘故,这里是一个演示了如何使用 kill() Perl 函数的 Proc::ProcessTable 示例。"9" 作为参数,是最强的 kill() 参数,大体意味着“不管三七二十一,杀死进程再说”。不要以 root 运行这条命令,除非真想杀死 inetd 进程。


清单 5:遍历进程,然后杀死所有 inetd
___FCKpd___4





回页首


结束语

UNIX 系统管理最让人失望的部分是 UNIX 供应商逃避标准而找到的各种方式。由于这种原因,当 Perl 单独应付 UNIX 系统中所有问题时,它是无能为力的。如果没有象 cfengine 这样的工具,象密码文件语法、共享文件系统以及跟踪日志等问题很快就变得无法管理。然而,还是存在一些希望;毕竟,我们只是查看了 Perl 可简化系统管理的一些方法。

Perl 与 cfengine 结合得很好。可以用 Perl 生成定制的 cfengine 配置,或者可以从 cfengine 运行 Perl 脚本。我用过这两者,发现集成不难。然而, cfengine 受过分简单的配置语言和缺乏数据结构影响。我将在有关 cfengine 的未来文章中展开这一问题。

如果选择实现的话,本文中介绍的集中化配置文件策略应当是非常实用的。在我的站点上现在已经使用了六个月,而且获得了巨大成功。如果将完整的层次结构检入一个如 CVS 那样的版本控制系统,您还将享受到版本化系统文件的好处,即可以回复到已检入版本控制系统的任一状态。



参考资料

分享到:
评论

相关推荐

    《Perl 自动化系统管理》第2版[PDF]

    perl 是类UNIX系统管理的一个利器,维护系统如果不会Perl,最少也应该弄熟SHELL,两者都能得心应手当然最好。 Perl是一种脚本语言。 最初的设计者为拉里·沃尔(Larry Wall),它于1987年12月18日发表。Perl借取了C...

    PERL语言编程

    不过,随后 Perl 就开始风行,于是它就成了可以操作文件系统,进程管理,数据库管理,进行 C/S 编程和安全编程,web 信息管理,甚至可以进行面向对象和面向功能的编程的语言。而且这些功能并非只是在 Perl 这边,每...

    Perl 实例精解(第三版).pdf

    15.3.2 使用PPM在Windows系统上安装Perl模块 15.3.3 安装RDBMS 15.3.4 为MMS范例创建DSN 15.4 使用ADO和DBI访问MSS 15.4.1 Microsoft SQL Server--范例15-1和15-3的查询 15.4.2 范例15-1:ex1.p1在...

    学生成绩信息管理系统论文 JSP 完整版

    重点介绍了学生成绩管理系统的实现过程:包括系统分析、 系统调查、 数据库设计、功能设计、系统物理配置方案、 系统实现、系统测试以及系统功能简介。 关键词:JSP,J2EE,学生成绩维护系统,MySQL,Hibernate,...

    homematic:我用于家庭自动化系统的脚本(fritzbox,homematic ccu2)

    我通常不会在系统上使用其他模块/软件,因此无需添加即可正常工作。 WLAN Presence脚本( ) 路由器脚本,用于检测特定设备(通过以太网地址)或IP范围(例如来宾)的存在。 检测到时,它将调用带有状态标记的URL...

    操作系统(内存管理)

    文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半手工地管理内存,以及如何使用垃圾收集自动管理内存。 为什么必须管理内存 内存管理是计算机编程最为基本的...

    生产服务器部署规范.pdf

    初始化系统安装包 系统 包名 用途 Suse 服务器基本系统包 系统日常工具包 c/c++编译器和工具 用于程序的开发编辑 redhat Vim-enhanced Vim 编辑器 开发工具(Automaker、gcc、perl、 python..) 用于程序的开发编辑 ...

    Apache2.0中文手册(chm格式)

    管理员可以利用此功能进行定制以达到观感的一致。 简化了的配置 很多易混淆的配置项已经进行了简化。 经常产生混淆的Port和BindAddress配置项已经取消了; 用于绑定IP地址的只有Listen指令; ServerName 指令中...

    WEB安全测试

    2.6 在Linux, Unix或OS X上安装Perl和使用CPAN 34 2.7 安装CAL9000 35 2.8 安装ViewState Decoder 36 2.9 安装cURL 36 2.10 安装Pornzilla 37 2.11 安装Cygwin 38 2.12 安装Nikto 2 39 2.13 安装Burp Suite 40 2.14...

    内存管理内存管理内存管理

    文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来半手工地管理内存,以及如何使用垃圾收集自动管理内存。 为什么必须管理内存 内存管理是计算机编程最为基本的...

    apache2 chm 手册

    管理员可以利用此功能进行定制以达到观感的一致。 简化了的配置 很多易混淆的配置项已经进行了简化。 经常产生混淆的Port和BindAddress配置项已经取消了; 用于绑定IP地址的只有Listen指令; ServerName 指令中...

    生产服务器部署规范.docx

    anacron 一个自动化运行任务守护进程 crond 计划任务守护进程 hald 设备的属性管理 dbus-daemon 是一个应用程序,它使用这个库来实现messagebus守护进程 Pcscd 用于监视进程活动的工具 portmap 主要功能是把RPC程序...

    网管教程 从入门到精通软件篇.txt

    Windows XP(包括 Windows 2000)的控制台命令是在系统出现一些意外情况下的一种非常有效的诊断和测试以及恢复系统功能的工具。小编的确一直都想把这方面的命令做个总结,这次辛苦老范给我们整理了这份实用的秘笈。 ...

    Linux环境数据库管理员指南

    1.3.1 功能丰富 3 1.3.2 多任务 4 1.4 为什么选择 Linux 6 1.4.1 何时使用 Linux 6 1.4.2 服务器与工作站 6 1.4.3 推荐的硬件 7 1.4.4 移植到 Linux工作站 7 1.5 Linux分发包 8 1.6 升级或移植前的考虑 10 1.6.1 ...

    MySQL 5.1官方简体中文参考手册

    1.4. MySQL数据库管理系统概述 1.4.1. MySQL的历史 1.4.2. MySQL的的主要特性 1.4.3. MySQL稳定性 1.4.4. MySQL表最大能达到多少 1.4.5. 2000年兼容性 1.5. MaxDB数据库管理系统概述 1.5.1. 什么是MaxDB? 1.5.2. ...

    MySQL 5.1参考手册

    1.4. MySQL数据库管理系统概述 1.4.1. MySQL的历史 1.4.2. MySQL的的主要特性 1.4.3. MySQL稳定性 1.4.4. MySQL表最大能达到多少 1.4.5. 2000年兼容性 1.5. MaxDB数据库管理系统概述 1.5.1. 什么是MaxDB? ...

    MisterHouse: Home Automation with Perl-开源

    MisterHouse是用Perl编写的Windows / Unix家庭自动化程序。 它可以响应语音命令,Web浏览器,一天中的时间,串行端口和X10数据,外部文件等,并且可以通过“文本到语音”引擎讲话。 支持位于...

    MYSQL中文手册

    1.4. MySQL数据库管理系统概述 1.4.1. MySQL的历史 1.4.2. MySQL的的主要特性 1.4.3. MySQL稳定性 1.4.4. MySQL表最大能达到多少 1.4.5. 2000年兼容性 1.5. MaxDB数据库管理系统概述 1.5.1. 什么是MaxDB? ...

Global site tag (gtag.js) - Google Analytics