磨刀不誤砍柴工 Puppet語法詳解
本文將介紹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, title的作用是讓puppet能唯一標識這個資源。第三行的name指定了要對那個文件操作,默認情況下,name都等于title,所以很多時候name是可以省略的。這點要注意。看下面的例子:
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這個軟件包配置好了。#p#
二、 類和函數
類的作用是把一組資源收集在一個盒子里面,一起使用,例如把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 . cfg " ; } package { " ssh " : ensure => i n s t a l l e d ; } s e r v i c e { " ssh " : ensure => running ; } }
這里,file /etc/ssh/sshd_config的內容是從puppet服務器上面下載的,file資源的內容可以從別的url得到,也可以erb模板生成,erb模板是很強大的工具,這個后面會說到。package資源安裝ssh軟件,service資源保證ssh服務在運行狀態。類的繼承這里就不講了,因為是入門手冊,另外用的不多。
puppet的官方文檔里面是沒有puppet函數這一說法的,而是叫做define ; 這里我寫做函數,是因為define實現的功能其實和函數一樣,而且在ruby里面也是用define來定義一個函數。這里寫做函數,便于理解。
具體來看一個例子:
define svn_repo ( $path ) { exec { " / 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庫。#p#
三、 節點
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 }
#p#
四、變量和數組
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 ' , ' xmlrpc ' ] : }
變量也有有效范圍,同其他語言一樣分為局部和全局變量,簡單說來,就是在里面定義的變量的使用范圍就限制在里面。同時,puppet還簡單的支持if ... eles 語法,但是用的不多,不在深入。
#p#
五、 模塊
簡單來說,一個模塊就是一個/etc/puppet/modues目錄下面的一個目錄和它的子目錄,在puppet的主文件site.pp里面用import modulename可以插入模塊。新版本的puppet可以自動插入/etc/puppet/modues目錄下的模塊。引入模塊,可以結構化代碼,便于分享和管理。例如關于apache的所有配置都寫到apache模塊下面。一個模塊目錄下面通常包括三個目錄,files, manifests,templates 。manifests 里面必須要包括一個init.pp的文件,這是該模塊的初始文件,導入一個模塊的時候,會從init.pp開始執行。可以把所有的代碼都寫到init.pp里面,也可以分成多個pp文件,init 再去包含其他文件。
files目錄是該模塊的文件發布目錄,puppet提供一個文件分發機制,類似rsync的模塊。templates 目錄包含erb模型文件,這個和file資源的template屬性有關。
puppet安裝好以后,modules目錄是沒有的,自己建立一個就行,然后在里面可以新增加你的模塊。請養成使用模塊的習慣。
【編輯推薦】
【責任編輯:李晶 TEL:(010)68476606】