天天看點

puppet自動化運維之exec資源

Puppet通過exec來執行外部的指令或者腳本,一般來講是shell腳本。

這裡面就涉及到一個重複執行的問題,因為預設的agent一連接配接上來就會自動執行對應的指令或者腳本。如果腳本重複執行對系統沒影響的還無所謂,如果會對系統造成影響呢?

一個有用的方法是使用像creates參數來,除非達到了某個條件才會運作指令。比如執行之前判斷檔案是否存在等等。你可以使用refreshonly參數限制一個exec隻有收到某個事件才執行。

作用:

    ①、遠端執行系統指令,其實就是shell的調用;

②、由于exec是一次性執行資源,在不同類裡面exec名字可相同。

格式:

exec {"title":              #一般寫上要執行的指令,如不寫,則需要指定command

    cwd => "目錄的絕對路徑",    #在那個目錄下執行,也可不要

    path =>   "/bin:/sbin:...",   #指令執行的搜尋路徑,如不要,需指定指令的絕對路徑

    command => "執行的指令",    #寫上要執行的指令,一般不需要,可在title中寫上

    creates => "檔案名(絕對路徑)",#當且僅當,該檔案名不存在,指令才被執行,可不要

    user => "使用者名",       #定義運作指令的使用者。 注意如果你使用了這個參數,那麼任何的錯誤輸出不會在當下被捕捉

    logoutput =>   "true|false",  #是否記錄輸出,可取的值為:true,false和其他合法的日志等級。

    onlyif => "指令",       #如onlyif中指令的執行結果為0(執行正确),才執行title或command中的目錄,與unless相反

    unless => "指令",       #如unless中指令的執行結果不為0(執行出錯),才執行title或command中的目錄,與onlyif相反

}

puppet執行外部指令,多次反複用這個方式執行指令是有威脅性的,是以建議對執行的指令進行加鎖或者類似的處理.

建議每個exec資源的名字最好是唯一的.

建議屬性值的目錄、指令或檔案,最好是絕對路徑

exec 參數介紹:

command     command => "執行的指令",

将會被執行的指令,必須為被執行指令的絕對路徑,或者得提供該指令的搜尋路徑。如果指令被成功執行,所有的輸出會被記錄在執行個體的正常(normal)日志裡,但是如果指令執行失敗(既傳回值與我們所指定的不同),那麼所有的輸出會在錯誤(err)日志中被記錄。這個是exec資源類型的名變量(namevar)。

creates     creates => "檔案名(絕對路徑)",

指定指令所生成的檔案。如果提供了這個參數,那麼指令隻會在所指定的檔案不存在的情況的被執行,下次的時候,該檔案存在了,就不在執行指令。

create屬性表明該exec将建立一個檔案,當下一次puppet執行的時候,如果發現了這個檔案,就不再執行這個exec資源。

cwd         cwd => "目錄的絕對路徑",

指定指令執行的目錄。如果目錄不存在,則指令執行失敗。

user        user => "使用者名",

定義運作指令的使用者。 注意如果你使用了這個參數,那麼任何的錯誤輸出不會在當下被捕捉,這是Ruby的一個bug。

If you are using Puppet to create this user, the exec will automatically require the user, as long as it is specified by name

onlyif      onlyif => "指令",

如onlyif中指令的執行結果為0(執行正确),才執行title或command中的目錄,與unless相反。例如:

exec { "logrotate": path => "/usr/bin:/usr/sbin:/bin", onlyif => "test `du /var/log/messages | cut -f1` -gt 100000" }

隻有在test傳回true的時候logrotate才會被運作。

需要注意的是onlyif定義的指令跟主指令遵循同樣的規則,也就是說如果path沒有被設定的話,需要使用絕對路徑。

除此之外,onlyif還可以接受數組做為其值,例如:

onlyif => ["test -f /tmp/file1", "test -f /tmp/file2"]

上面的代碼限定了隻有在所有數組中的條件傳回true時exec才會被執行。

unless      unless => "指令",

如unless中指令的執行結果不為0(執行出錯),才執行title或command中的目錄,與onlyif相反。例如:

exec { "/bin/echo root >> /usr/lib/cron/cron.allow":

            path => "/usr/bin:/usr/sbin:/bin",

            unless => "grep root /usr/lib/cron/cron.allow 2>/dev/null"

            }

上面這段代碼先用grep在cron.allow檔案(Solaris系統中)中找root,如果沒有找到,就寫入root。

要注意的是這個參數裡的指令跟主指令遵循同樣的規則,也就是說如果path沒有被設定的話,需要使用絕對路徑。

path        path => "/bin:/sbin:...",

指令執行的搜尋路徑。如果path沒有被定義,指令需要使用絕對路徑。路徑可以以數組或以冒号分隔的形式來定義。

logoutput   logoutput => "true|false|on_failure",

是否記錄輸出。預設會根據exec資源的日志等級(loglevel) 來記錄輸出。若定義為on_failure,則僅在指令傳回錯誤的時候記錄輸出。可取的值為:true,false和其他合法的日志等級。

env:

我們不建議使用這個參數,請使用‘environment’。這一部分還未完成。

environment

為指令設定額外的環境變量。要注意的是如果你用這個來設定PATH,那麼PATH的屬性會被覆寫。多個環境變量應該以數組的形式來設定。

group

定義運作指令的使用者組。在不同的平台下的運作的結果無法确定,由于不同使用者運作指令的時候,變量是不變的,是以這是平台的問題,而不是Ruby或Puppet的問題。

refresh

定義如何更新指令。當exec收到一個來自其他資源的事件時,預設隻會重新執行一次指令。不過這個參數允許你定義更新時執行不同的指令。

refreshonly

該屬性可以使指令變成僅重新整理觸發的,也就是說隻有在一個依賴的對象被改變時,指令才會被執行。僅當指令與其他對象有依賴關系時,這個參數才有意義。當你要觸發某個行為時,會顯得很有用:

file { "/etc/aliases":

source =>   "puppet://server/module/aliases"

exec { newaliases:

path =>   ["/usr/bin", "/usr/sbin"],

subscribe =>   File["/etc/aliases"],

refreshonly => true

要注意的是隻有subscribe和notify可以促發行為,而不是require,是以在使用refreshonly時,隻有同時使用subscribe或notify才有意義。有效的值為true, false。

returns

指定傳回的代碼。如果被執行的指令傳回了其他的代碼,一個錯誤(error)會被傳回。預設值是0,可以定義為一個由可以接受的傳回代碼組成的數組或單值。

timeout     timeout => "秒數",

指令運作的最長時間。如果指令運作的時間超過了timeout定義的時間,那麼這個指令就會被終止,并作為運作失敗處理。當定義為負值時就會取消運作時間的限制。timeout的值是以秒為機關的。

exec資源在不到萬不得已的時候不要去用,簡單說來exec資源就是在執行puppet的時候,調用shell執行一條shell語句,例如:

exec {"delete config":

path => "/bin:/usr/bin",

command => "rm /etc/ssh/ssh_config";

exec資源是不太好掌控的資源,如果能用腳本實作,盡量寫成腳本通過file資源分發到伺服器上面。然後用其他的方式來調用腳本。例如crontab。或你完全可以用file資源來把crontab任務放到/etc/cron.d目錄下來實作crontab資源的管理。使用puppet的時候,盡量用最簡單的文法,越是花哨的文法也越容易出錯。

執行個體:

#creates

vi /etc/puppet/manifest/test.pp

#注意指令要使用絕對路徑

Exec { path => [ "/bin/", "/sbin/" ,   "/usr/bin/", "/usr/sbin/" ] }

exec { "/tmp/test1":

         command =>   "touch /tmp/exec_test1",

         creates =>   "/tmp/exec_test1";

#check

ls: cannot access /tmp/exec_test1: No such file or directory

info: Caching catalog for client.perofu.com

info: Applying configuration version '1395071830'

notice: /Stage[main]//Exec[/tmp/test1]/returns:   executed successfully

notice: Finished catalog run in 0.32 seconds

-rw-r--r-- 1 root root 0 Mar 17 23:58 /tmp/exec_test1

#此時creates的參數已滿足,就不會再執行了

notice: Finished catalog run in 0.23 seconds

#onlyif

exec {"rm -rf /var/log/mysqld.log.bak":

        logoutput => "on_failure",

        onlyif =>   "[ $(cat /var/log/mysqld.log.bak |wc -l) -gt 10 ]";

21

info: Applying configuration version '1395072287'

notice: /Stage[main]//Exec[rm -rf   /var/log/mysqld.log.bak]/returns: executed successfully

notice: Finished catalog run in 0.38 seconds

ls: cannot access /var/log/mysqld.log.bak: No such file or directory

     本文轉自yzy121403725 51CTO部落格,原文連結:http://blog.51cto.com/lookingdream/1845564,如需轉載請自行聯系原作者