本文将介绍puppet的语法,因为puppet是用ruby编写的,因此puppet的语法也和ruby类似,都是很简单的面对对象的高级语言。再次强调,puppet把需要管理的内容抽象成为资源,每种资源有不同的属性,因此puppet语言就是描述这些资源的属性以及资源之间关系的语言。 一、资源
定义一个资源,需要指定资源的类型和资源的title。看一个例子:
f i l e {
" / etc /passwd" :
name => " / etc / passd " ,
owner => root ,
group => root ,
mode => 644;
}
上面的代码让/etc/passwd的权限保持644,并且属于root用户和root用户组,file是指定资源的类型是"file"类型,第二行的"/etc/passwd"是资源的title,>f i l e {
" sshdconfig " :
name => $operatingsystem ? {
s o l a r i s => " / usr / l o c a l / etc / ssh / sshd_config " ,
default => " / etc / ssh / sshd_config " ,
} ,
owner => root ,
group => root ,
mode => 644 ,
}
资源的title是sshdconfig,但是name却可以通过判定操作系统自己选择合适的值。这样,当其他的资源要依赖sshdconfig的时候,只需要说明依赖sshdconfig就行,不需要关心文件到底在什么路径下面。例如下面的代码:
s e r v i c e { " sshd " :
subscribe => F i l e [ sshdconfig ] ,
}
指定了一个sshd的服务,这个服务如果发现文件资源sshdconfig 有变动,就会自己reload配置文件。是不是很方便呢?注意上面的subscribe后面的File,第一个字母要大写,定义资源关系的时候,这里的字母要大写。
通常,在puppet代码里面可能会定义很多相同的资源,可以用[]把所有资源的title写在一起,例如:
f i l e {
[ " / etc /passwd" , " / etc / hosts " ] :
owner => root ,
group => root ,
mode => 644;
}
你可能已经发现了,每次定义文件的时候如果都输入mode,owner,group会很繁琐,因此你可以在puppet的site.pp的开头定义资源的默认值。定义资源的默认值需要把资源的第一个资源大写。例如下面的代码让所有的file资源的mode是644,owner是root。
F i l e { owner => root , mode => 644 ; } 默认值可以被后面的设置覆盖。
在puppet里面可以定义资源之间的关系,例如前面提到的,如果sshdconfig文件如果有修改,sshd服务就重启。puppet里面还有另一个资源关系,依赖。例如资源A依赖资源B,如果资源B不存在,资源A就不被执行。定义资源依赖的属性是requre 。例如:
f i l e {
" / etc / apache2 / port . conf " :
content => "80" ,
require => Package [ "apache2" ] ;
}
package {
"apache2" :
ensure => i n s t a l l e d ;
}
file资源设置port.conf的内容为80,但是在设置file资源之前,要求apache2这个软件包配置好了。 二、 类和函数
类的作用是把一组资源收集在一个盒子里面,一起使用,例如把sshd和他的配置文件做成一个ssh类,其他的地方要用到就直接包含ssh类就可以了,方便写出更简洁的代码,便于维护。类可以继承。看一个具体的例子:
c l a s s ssh {
f i l e {
" / etc / ssh / sshd_config " :
source => "puppet : / / $ f i l e s e r v e r / ssh / sshd_config
" / usr / bin /svnadmin? create ?$path / $ t i t l e " :
unless => " / bin / t e s t ???d?$path " ,
}
}
svn_repo {
puppet_repo :
path => " / var / svn_puppet " }
svn_repo {
other_repo :
path => " / var / svn_other " }
首先用define定义了一个svn_repo函数,并且带了一个参数1 。这个参数可以在函数里面的资源使用,在这里,exec资源根据提供的参数创建svn 仓库。函数定义好以后,后面的两行就用定义好的函数创建了两个svn库。 三、 节点
puppet如何区分不同的客户端,并且给不同的服务端分配manifest呢?puppet使用叫做node的语法来做这个事情,node 后面跟客户端的主机名3,例如下面的例子:
node ' host1 . example . com ' {
include ssh
}
node ' host2 . example . com ' {
include apache , mysql , php
}
当主机host1.example.com来连服务端时,只会执行node 'host1.example.com'里面的代码,不会执行node host2.example.com里面的代码。正如前面所说,可以定义一个default结点。比如没有针对host3的node配置,host3就用default的配置了。在这里include的意思是include 类。同样,节点也支持继承,同样,也不打算深入。
使用节点的时候,尽量把所有的配置写成类,节点里面定义好变量和包含相应的类就可以了。保证代码的简洁。例如:
1、因为可以带参数,所以我觉得翻译成函数更好
2、注意看函数的使用语法,是不是和使用资源一样,path可以看作是属性
3、主机名在puppet里面很重要
node ' host4 . example . com ' {
$networktype=" t e l e "
$nagioscheckport=" 80 ,22 ,3306 "
include ssh , apache , mysql
} 四、变量和数组
puppet也和其他语言一样,支持变量和数组,puppet用$符号定义变量,变量的内容用双引号括起来。例如:
$test=" hello , guys "
f i l e {
" /tmp/ t e s t " :
content => $test ;
}
puppet可以使用由facter提交的变量,facter在客户端收集系统信息整理成不同的变量提交给puppet服务器端,服务器端的代码可以使用这些变量实现高级的功能,例如不同的硬件配置生成不同的应用软件配置文件。运行facter命令可以看到很多变量的输出,这些变量可以在puppet代码里面直接使用。
puppet利用方括号来定义数组,数组的内容由逗号分割,例如下面的例子:
[ "apache2" , " httpd " , " ssh " ] 数组可以用在资源定义里面,例如前面提到的例子。也可以用在函数里面,例如:
define php : : pear ( ) {
package { " `php??$ {name} " : ensure => i n s t a l l e d }
}
php : : pear { [ ' ldap ' , ' mysql ' , ' ps ' , 'snmp ' , ' s q l i t e ' , ' t i d y ' , '