歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Unix知識 >> 關於Unix

功能豐富的Perl:用於系統管理

cfengine(配置引擎)是一種 UNIX 管理工具,其目的是使簡單的管理的任務自動化,使困難的任務變得較容易。它的目標是使系統從任何狀態收斂(convergence)到一種理想狀態。依照它的作者 Mark Burgess 所說,cfengine 總是使您的系統更接近於您所定義的配置
  cfengine(配置引擎)是一種 UNIX 管理工具,其目的是使簡單的管理的任務自動化,使困難的任務變得較容易。它的目標是使系統從任何狀態收斂(convergence)到一種理想狀態。依照它的作者 Mark Burgess 所說,cfengine 總是使您的系統更接近於您所定義的配置; 它決不會使系統變得更糟。在本文中,Ted 通過演示一些簡單的 cfengine 使用,使您熟悉這一獨特的系統管理工具。
  
  初學者和中級系統管理員將從本文獲益最多;解說和示例假設您可以運用大部分初學者級別的系統管理概念。
  
  要使用本文中的示例,您的系統應該是一個最近的(2000 或更新)主流 UNIX(Linux、Solaris、BSD)安裝。示例可以與早期版本的 Perl 和 UNIX 以及其它操作系統一起使用,如果它們不能工作,對您來說,可以把它當成練習來解決。
  
  cfengine 正處於開發中。版本 1.6.3 是穩定的,它是本文的基礎。當前正在進行阿爾法測試的版本 2.0 的計劃包括重寫體系結構、添加許多很棒的新功能部件以及使語法基本上保持不變。要了解 cfengine 的所有功能以及版本 2.0 中的增強功能,請訪問 cfengine主頁(請參閱本文後面的參考資料)。
  
  cfengine 的要點
  cfengine 將改變您的系統管理方法。您將運行一個命令並觀察系統將收斂到一種穩定狀態。我保證這看起來象在變魔術。在您喝茶的時候,cfengine 將編輯文件、運行命令並創建符號鏈接。
  
  然而,cfengine 並不能代替您思考。在將配置文件放入產品之前,您仍需要編寫它並對它進行測試。 而另一方面,cfengine 所做的事情幾乎很少會造成損害。
  
  cfengine 使系統收斂成為可能。但是,為什麼需要收斂呢? 我認為系統管理員首先需要保持內心寧靜,其余的事情都是次要的。穩定性、可靠性和可預測性是達到內心寧靜的方法。這看似過分簡單, 但詢問任何一名好的系統管理員,每次您都會得到這個答案。收斂可以幫助管理員達到穩定性、可靠性和可預測性。雖然它不是達到那些目標的唯一方法,但在我的經歷中它所帶來的痛苦最少。
  
  穩定性可定義為防止無意的更改。當 cfengine 實現收斂時,它通過規則集做到這一點。良好設計的規則(請放心,cfengine 使良好的設計變得容易)只是使系統達到一種理想狀態(如在 cfengine 規則中定義的那樣理想)。例如,每次運行 cfengine 時,都可以重新創建關鍵的系統符號鏈接。或者,只要修改了本地副本,都可以從可信資源庫復制 init.d 啟動腳本。 如果 cfengine 沒有發覺進程在運行,那麼可以重新啟動它們。
  
  可靠性是使機器幸免於問題的能力。網絡出故障或磁盤出故障是主要的可靠性考驗。您的系統能幸免於那些問題嗎?通過收斂到一種理想狀態,您可以期望系統處於或接近那一理想狀態。 雖然可靠性不單由 cfengine 完成,但收斂可使之更加容易。 因為穩定的系統不太可能受問題影響,所以穩定性也是可靠性的主要資產。 最後,cfengine 的收斂使獲得“空白”系統並使它達到期望的狀態成為可能, 並能夠對關鍵系統進行快速臨時替換。
  
  這裡,有必要多講講期望和理想的狀態。目前為止,我們假設僅有一種理想狀態,它就是那個期望的狀態。事實上,對於所有機器來說並沒有理想狀態。 機器按任務、位置、連通性、用戶、操作系統類型和版本等分類。每個系統管理員都用某些方法來對他的機器分類,通常根據上述各項以及更多項(我們稍後將詳細討論類)。雖然對於所有機器來說沒有一種理想狀態,但對於給定的機器類有一個要達到的理想狀態。 這是 cfengine 的設計目標。cfengine 使尋找理想狀態變得可行,並且易於收斂到該狀態。
  
  可預測性是機器按照期望的那樣來運轉的能力。 收斂通過使系統變得穩定且可靠來達到可預測性。而且,一旦新機器收斂到一種理想狀態,就可以期望它象它所替換的舊機器那樣工作。當機器將很快收斂到一個已知狀態時,就可以很容易地估計添加系統或替換它們的調度成本。最後,為您系統編寫的軟件可以期望系統處於一種接近理想的狀態。然後,系統資源處於一種可預測的狀態,這樣,軟件就可以更多地集中在功能上,而更少地將每個系統作為懷有敵意的未知領域對待。
  
  cfengine 的概述
  Cfengine 由幾個程序組成。在版本 1.6.3 中,主程序叫作 cfengine。cfengine 程序解釋文件中的規則集,並執行那些規則請求的操作。 嚴格來說,cfengine 程序只是 cfengine 語言的解釋器,並且任何 cfengine 程序都只是那個解釋器的腳本。
  
  在版本 1.6.3 中,還有一個名為 cfd 的守護程序及其同伴 cfrun。cfd 將在版本 2.0 得到加強,而在 1.6.3 版本中有許多未完善的地方。幸運的是,不用 cfd,就可以完成我所需要的任務(用信號通知運行 cfengine 並遠程復制文件)。我寧願在 ssh 上通過顯式腳本啟動 cfengine。 它只比 cfd 少許慢一點,但更易於監控。當通過 cfd 啟動時,cfengine 發出的錯誤和遠程定義的類沒有可靠地顯示出來。 對於遠程文件復制,我發現 cfd 是不可靠的而且可能會危害安全性,所以我使用 rsync。cfengine 的作者 Mark Burgess 聲明 cfd 在版本 2.0 中將有很大改進,而 rsync 將不再是必需的,但在版本 2.0 推出之前,我建議避免 cfd。
  
  在開始使用 cfengine 之前,應該編譯和安裝它。對於可以使用它們的系統,RPM 都有可用的版本, 而且還有一個可用的 Solaris 包(請參閱參考資料)。如果要存儲文件的永久校驗和(類似於 Tripwire 所做的事情),則應該帶有 Berkeley DB 支持進行編譯。然後,應該開始創建配置文件。 主要的配置文件是 /etc/cfengine/cfengine.conf,它是在不帶文件名調用 cfengine 時運行的(當在 1.6.3 中編譯時,可以指定一個不同的缺省配置目錄,但在 2.0 及更高版本中,/etc/cfengine 將是檢查的唯一位置,所以您應該嚴格遵守這一點)。
  
  下面是 cfengine 的啟始配置。它不是成品, 在運行它之前,應該仔細地閱讀 cfengine 參考大全和教程(請參閱參考資料)。 請帶 -v -n(詳細的預演)選項嘗試運行 cfengine,看一下這個配置將做些什麼。 當使用 -n(預演)選項時,不會影響系統。
  
  清單 1. cfengine 的啟始配置文件 /etc/cfengine/cfengine.conf
  
  # note that only some of the possible sections are used here;
  # refer to the cfengine documentation for the full list of sections
  # you can have. Comments, as you can see, are like shell or Perl
  # comments.
  
  # see the tutorial and reference for any unexplained phenomena
  
  import:
   any::
   cf.groups
  groups:
  
  # all groups are defined in cf.groups, imported above, but you can
  # define extras here. The format is simple:
  
  class = ( machine1 machine2 )
  
  # and then any machine named machine1 or machine2 will have that class
  # defined.
  # the control section sets up how cfengine will behave
  control:
   any::
  # you have to state in AddInstallable what classes unknown to cfengine
  # by default you will be using. Run cfengine as "cfengine -v" to see
  # the built-in classes you don't have to define. Here we divide
  # machines into the ones that run inetd and the ones that run xinetd,
  # as an example.
   AddInstallable = ( inetd xinetd )
   editfilesize  = ( 300000 )
   moduledirectory = ( /etc/cfengine/modules )
   domain  = ( yourdomain.com )
   any::
   LogDirectory = ( /etc/cfengine/log )
   netmask  = ( 255.255.255.0 )
   Repository  = ( /etc/cfengine/repository )
   sysadm  = ( "[email protected]" )
   # Bug in cfengine: actionsequence must follow LogDirectory and Repository
   actionsequence = ( directories files editfiles copy links processes disable
                  shellcommands )
  directories:
  # this ensures that these directories will be created when cfengine runs
   /etc/cfengine/log
   /etc/cfengine/repository
   /etc/cfengine/cfcollector
  files:
   any::
  # set the permissions for these files
   /etc/sudoers mode=0440 owner=root group=root action=fixall
   /etc/hosts.allow mode=0644 owner=root group=root action=fixall
   /etc/hosts.deny mode=0644 owner=root group=root action=fixall
  # just warn if this file's permissions are wrong
   /etc/shadow mode=0400 owner=root action=warnall inform=true
  # CERT advisory CA-2001-05, for Solaris only
   solaris::
   /usr/lib/dmi/snmpXdmid mode=0000 owner=root group=root action=fixall
  # example of setting permissions differently for different OS types
  # (not Linux and Linux), and negating classes
   !linux::
   /.ssh mode=0700 owner=root action=fixall inform=true
   linux::
   /root/.ssh mode=0700 owner=root action=fixall inform=true
  editfiles:
   any::
  # add the rsync service to /etc/services and /etc/inetd.conf
   { /etc/services
    SetLine "rsync 873/tcp # rsync"
    AppendIfNoLineMatching "rsync.*"
   }
   { /etc/inetd.conf
    # add rsync
    SetLine "rsync stream tcp nowait root /usr/local/bin/rsync rsyncd --daemon"
    AppendIfNoLineMatching "rsync.*"
   }
  copy:
  # set up sshd startup script, from trusted master distribution in /etc/cfengine
   /etc/cfengine/sshd dest=/etc/init.d/sshd repository=/etc/cfengine/repository
  links:
   any::
  # link the sshd init.d script to /etc/rc3.d, overwriting existing
  # links if they exist
   /etc/rc3.d/S72local_sshd ->! /etc/init.d/sshd
  processes:
  # invoke cfengine with "cfengine -DHupInetd" to define this class and
  # send inetd the HUP signal (the machine has to be in the inetd class
  # discussed above, too). This is an example of compound classes.
   inetd.HupInetd::
   "inetd" signal=hup
  disable:
  # empty this file (this can also be used to rotate logs, with
  # different rotate options)
   /etc/rc3.d/S77dmi rotate=empty
  shellcommands:
   any::
  # always put the contents of the $domain variable in this file.
  # note that all the cfengine variables can be interpolated inside strings.
   "/bin/echo $(domain) > /etc/cfengine/cfdomainname"
  
  簡單用法:編輯和復制文件
  要編輯文件,使用 editfiles 節。其語法相當復雜,但在我們的示例中將僅使用幾條可能的命令。有關所有命令,請參閱 cfengine 參考大全(請參閱參考資料)。
  
  清單 2. 編輯文件 editfiles:
   development::
   { /etc/sudoers
    DeleteLinesContaining "cpa "
   }
   aclearcase/" target="_blank" >ccounting::
   { /etc/sudoers
    SetLine "cpa ALL=(ALL) ALL"
    AppendIfNoLineMatching "cpa .*"
   }
  
  在清單 2 中,我們看到當用戶“cpa”從 Development 部門移到 Accounting 部門時發生的情況。必需取消他對 Development 機器的 sudo 訪問權, 同時他需要對 Accounting 機器的 sudo 訪問權。我們使用您應該已經在 AddInstallable() 下的 control: 節中聲明的機器類。根據機器類,采取適當的操作。請注意,名為“cpa1”的用戶在這些規則中不會出現問題, 因為在“a”的後面我們明確地請求了一個空格。
  
  另一個簡單的通用用法是復制文件。在清單 1 中的框架示例中,我們看到設置 sshd 的 copy: 和 links: 節,它們是干什麼的呢?
  
  清單 3. 復制文件 copy:
  # set up the sshd startup script
   /etc/cfengine/sshd dest=/etc/init.d/sshd repository=/etc/cfengine/repository
  links:
   any::
  # link the sshd init.d script to /etc/rc3.d
   /etc/rc3.d/S72local_sshd ->! /etc/init.d/sshd
  
  在我們的站點上,在運行 cfengine 之前,我們使用一個中央可信位置來執行 rsync /etc/cfengine。也就是說,/etc/cfengine 是我們要使用的可信文件的本地副本。/etc/cfengine/sshd 是其中一個文件,它是 SSH 守護程序的啟動腳本。然後,如果可信的啟動腳本與 /etc/init.d 中的腳本不同,則 copy: 節會將該腳本復制到該目錄中。 這樣,惡意的攻擊者將看到他的更改不見了(我們以這種方式維護大多數 /etc/init.d 腳本)。同樣,可以用“signalled pull”方法以這種方式方便地傳播啟動腳本中的更改。
  
  copy: 的 repository 選項只是告訴 cfengine 放置舊 sshd 腳本的位置(如果必須覆蓋它)。該選項是防止意外事件發生的可靠保障。
  
  links: 節產生到正確啟動目錄的鏈接。請注意這是 Solaris 或 System V 啟動層次結構。Linux 的等價啟動層次結構將在 solaris::/linux:: 類部分中處理,但是這一代碼片段使用簡單的方法來使示例更簡單。驚歎號(!)是可選的,它表示是否應該覆蓋現有的鏈接(從不覆蓋現有文件)。
  
  可以立即復制或鏈接整個目錄的內容。 例如,可以一次將 /etc/cfengine/sbin 中的所有文件復制或鏈接到 /usr/local/sbin。僅產生必需的副本或鏈接。cfengine 允許 copy: 命令帶遠程復制選項,但這些復制是通過 cfd 完成的, 我發現由於 cfd 本身的問題,它們對於生產環境是不夠的。預先運行 rsync 是 cfengine 1.6.3 及更低版本的較好選項。
  
  高級用法:重新啟動進程
  最好用定期運行的 cfengine 子配置來處理進程,它通常存儲在 /etc/cfengine/cf.minute 或相似的文件中。 使 cf.minute 包含 cfengine.conf 使用的相同 cf.groups 組定義,並用 cfengine -f /etc/cfengine/cf.minute 調用它。
  
  下面的示例演示如何重新啟動進程或向它們發信號。
  
  清單 4. 重新啟動進程或向它們發信號 processes:
   any::
  # restart cfd if it's not running already
   "/usr/local/sbin/cfd" restart "/etc/init.d/start-cfd start"
  # restart sshd if it's not running already
   "/usr/local/sbin/sshd" restart "/etc/init.d/sshd start"
  # HUP inetd if the HupInetd class is defined, see listing 1
   inetd.HupInetd::
   "inetd" signal=hup
  
  cfd 是 cfengine 守護程序。盡管頻繁地重新啟動,但經過證實它相當不穩定, 這就是我使用版本 1.6.3 時拋棄它的原因。2.0 和更新版本的守護程序應該會更好。
  
  象任何計算機軟件一樣,作為一個組的守護程序軟件會經歷各種各樣實現。 對於 cfengine 而言, 有兩種類型的守護程序:使用 fork 和 exit 的守護程序(inetd、sshd 和 cfd 是這種類型的最好示例), 和不使用 fork 和 exit 的守護程序(例如,qmail 啟動守護程序)。
  
  我個人相信守護程序應該有可選的任一行為,所以我們不會有兩種類型完全不同的程序要監控。但現在它不是大多數守護程序的選項,所以我們不得不應付它。
  
  對於使用 fork 和 exit 的守護程序,cfengine 運行得很順利。守護程序創建子進程,而 cfengine 繼續其愉快的“旅程”。然而,對於不創建子進程的守護程序(並且這包括大多數內部守護程序軟件),cfengine 需要特殊幫助。在版本 2.0 中,應該以某種方式解決這一問題, 但在版本 1.6.3 中,軟件必須打印出後跟回車的“cfengine-die”, 以便讓 cfengine 知道保留它是安全的。還可以用類似由 Dan Bernstein 開發的 daemontools(請參閱參考資料)軟件來監控不創建子進程的守護程序,但這本身就是一種冒險。通常更加容易的方法是: 將 print 語句放到程序中,這樣的臨時修補不會影響任何其它東西。
  
  結束語
  本文簡要地介紹了 cfengine 可做的事情。您應該自己嘗試它,特別在浏覽了 cfengine 參考大全之後,看看 cfengine 對您有什麼樣的幫助。
  
  按照我的經驗,除了 cfd 守護程序外,版本 1.6.3 非常穩定。 語法將轉入下一個版本(2.0),可能會增加一些內容,所以您將要花時間去學習它。
  
  cfengine 是一種獨特的系統管理工具。即使您沒有決定使用它,但其概念和執行將對您的工作產生幫助。如果您決定使用它,您將發現 cfengine 無限的靈活性和驚人的用處。

Copyright © Linux教程網 All Rights Reserved