设为首页 收藏本站
查看: 959|回复: 0

[经验分享] 功能丰富的 Perl: 使用 Perl 自动化 UNIX 系统管理

[复制链接]

尚未签到

发表于 2017-5-19 08:31:07 | 显示全部楼层 |阅读模式



DSC0000.gif



文档选项

<!--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 那样的版本控制系统,您还将享受到版本化系统文件的好处,即可以回复到已检入版本控制系统的任一状态。



  参考资料


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-378915-1-1.html 上篇帖子: Perl语言的胶水作用_实现前后台对接 下篇帖子: perl utf8 encoding decoding HTML::Entities Perl中字符串编码的处理
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表