2016-07-07 27 views
3

我希望能夠保證在給定主機上成功執行長時間運行的shell命令後,它不會在該主機上的後續劇本運行中執行。如何確保每個主機只執行一次Ansible shell命令?

我很高興獲悉了Ansible shell任務的creates選項(請參閱http://docs.ansible.com/ansible/shell_module.html);使用這個我可以創建一個文件,一個shell命令運行成功後,並沒有該命令在以後運行時執行:

- name: Install Jupiter theme 
    shell: wp theme install ~/downloads/jupiter-theme.zip --activate 
     && touch ~/ansible-flags/install-jupiter-theme 
    args: 
    creates: ~/ansible-flags/install-jupiter-theme 

正如你所看到的,我有一個目錄ansible-flags在我主動的主目錄,這些控制文件用戶(deploy)。

但是,這是一個相當混亂。有一個更好的方法嗎?

此外,當我需要以不同的用戶身份運行一個步驟時,情況會變得更加複雜;在這種情況下,我無法訪問deploy主目錄及其子目錄。當然,我可以授予訪問權限,但這增加了更多的複雜性。你會如何推薦我處理這個問題?

回答

2

Ansible本身是無狀態的,所以你使用的任何技術都需要由你自己來實現。沒有比告訴Ansible只能運行一次任務更簡單的方法。

我認爲你已經是相當簡單了。也許使用另一個路徑來檢查。我很確定wp theme install實際上會將該zip文件提取到某個位置,然後您可以將其與creates選項一起使用。

有辦法,但沒有什麼使得它更容易:

  • 在你喜歡的檢查爲主題的任何語言,創建一個腳本,如果沒有安裝,安裝它。而不是shell任務,那麼你可以用script module執行腳本。

  • /etc/ansible/facts.d中安裝local fact,它檢查已安裝的主題。然後,您可以簡單地將基於該事實的條件應用於shell任務。

  • 設置fact caching,然後註冊shell任務的結果並將其存儲爲事實。通過啓用事實緩存,您可以在以後的Playbook運行中訪問存儲的結果。

它只是變得更加複雜。 creates選項非常適合這種情況,如果您使用的命令提取zip的位置,它也很乾淨。

當然,如果您需要從其他用戶帳戶訪問該文件,則需要授予該文件的訪問權限。將權限設置爲只能由擁有者讀取的東西存儲在用戶主目錄中確實不是理想的解決方案。

+0

我提供的示例的WordPress主題,出於某種原因,我認爲主題將安裝在數據庫中,而不是文件系統;這就是爲什麼我創建了一個人造的控制文件,但是您是對的,我可以查找在主題安裝期間創建的主題目錄。 (回想起來,即使它存儲在數據庫中,我也應該試圖找到一種方法來查詢數據庫中的那條信息。) –

+0

謝謝您花時間回答我的問題。我現在看到,對於無法使用「創建」的情況,確實沒有更簡單的方法來執行我想要的操作。 –

3

你的劇本應該是冪等的!
因此任一個任務都應該安全地執行多次(例如echo ok),或者您應該檢查是否應該執行它。
你的任務可能是這樣的:

- name: Install Jupiter theme 
    shell: wp theme is-installed jupiter || wp theme install ~/downloads/jupiter-theme.zip --activate 

它會檢查是否安裝了木星的主題,將僅運行如果沒有安裝主題wp theme install
但是這會在任何情況下將任務的結果標記爲changed
要使它很好,你可以這樣做:

- name: Install Jupiter theme 
    shell: wp theme is-installed jupiter && echo ThemeAlreadyInstalled || wp theme install ~/downloads/jupiter-theme.zip --activate 
    register: cmd_result 
    changed_when: cmd_result.stdout != "ThemeAlreadyInstalled" 

首先,它會檢查是否已經安裝了木星的主題。
如果是這樣,它會輸出ThemeAlreadyInstalled並退出。
否則它會打電話給wp theme install
該任務的結果已註冊到cmd_result
我們用戶changed_when參數陳述的事實,如果ThemeAlreadyInstalled ansible不應該考慮改變任務,所以它在你的劇本輸出中仍然是綠色的。

如果您之前wp theme install(如下載的主題)做了一些準備工作,你可能需要運行測試作爲單獨的任務來登記結果,並在隨後的任務使用when條款:

- name: Check Jupiter theme is installed 
    shell: wp theme is-installed jupiter && echo Present || echo Absent 
    register: wp_theme 
    changed_when: false 

- name: Download theme 
    get_url: url=... 
    when: wp_theme.stdout == "Absent" 

- name: Install Jupiter theme 
    shell: wp theme install ~/downloads/jupiter-theme.zip --activate 
    when: wp_theme.stdout == "Absent" 
+0

我理解需要是冪等的,但我不認爲這個問題與此有任何關係 - 假設重複一個不必要的步驟會產生與*不重複的步驟相同的結果,這是無論如何都是冪等的,不是嗎? 這裏的問題是如何防止不必要的任務執行,以節省時間。 –

+0

我已經使用您的建議來準確報告任務是否實際執行。很酷的東西,非常感謝! –

+0

@KeithBennett,爲了防止執行你需要測試。我敢打賭,你實際上並不想爲每個主機運行一次命令,但要確保每次執行劇本時都安裝主題(如果它已經存在,就不要安裝它)。想象一下標誌文件在那裏,但有人手動刪除了主題。在這種情況下,您需要安裝主題時爲true的測試,否則爲false。我認爲在安裝之前用'wp'命令檢查它是一個好的舉措。 –