我嘗試經常使用 Ansible,即使對於我知道如何使用 shell 腳本完成的任務,因為我知道 Ansible 易於擴展。 即使我可能僅為我的個人工作站開發 Ansible playbook,但有時它最終會比預期的更有用,並且很容易將相同的 playbook 應用於我網絡上的所有計算機。 而且,有時真正擅長某事的最大敵人是認為它僅適用於專業人士、大型項目或任何你覺得自己不是的東西。 我使用 Ansible 是因為它是一個很棒的開源工具,但我從中受益最多是因為它可以擴展。
我最近分配給 Ansible 的任務之一是整理我的下載文件夾的巨大任務。 如果你和我一樣,你最終會從互聯網上下載許多文件,然後忘記這些文件的存在。 一方面,我不介意這個習慣。 有時我會意識到我仍然需要下載文件夾中的文件,因此忘記文件而不是立即刪除文件可能會有所幫助。 但是,還有其他一些文件,我下載它們只是為了使用一次,然後應該刪除它們。
我決定使用一個高度特定的 Ansible 任務來查找我知道我不需要的文件,然後刪除它們。
Ansible 樣板文件
Ansible playbook 通常以完全相同的方式開始:定義你的主機並宣告一個任務
---
- hosts: localhost
tasks:
將這三行記在腦海中。 它們是 Ansible playbook 的 “shebang” (#!
)。 一旦你在文本文件中有了這些行,你就可以開始定義任務中的步驟。
使用 Ansible 查找文件
你可以使用 find
Ansible 模組 在系統上查找文件。 如果 Ansible 模組是一個命令,則其參數是其 命令選項。 在這個 playbook 示例中,我想查找明確位於 ~/Downloads
文件夾中的文件,我可以使用 paths
參數來定義它。
這是我開始編寫 playbook 時的流程:我在 Ansible 模組索引中找到一個看起來可能執行我需要的操作的模組,然後我通讀其參數以了解我對該模組的控制程度。
在我的情況下,我意外收集在下載文件夾中的文件是 CSV 文件。 它們每週下載、處理,然後應該消失。 但它們會掛在那裡幾週,直到我感到不知所措並刪除它們。 以下是如何使用 Ansible 在下載中查找 CSV 文件
---
- hosts: localhost
tasks:
- name: Find CSV in Downloads
find:
paths: ~/Downloads
recurse: false
patterns: '*.csv,*.CSV'
register: result
paths
參數告訴 Ansible 在哪裡搜索文件。
recurse: false
參數禁止 Ansible 在下載的子目錄中搜索。 這使我能夠保留我下載並保存到子目錄中的 CSV 文件。 Ansible 僅針對我直接保存到下載的 CSV 文件(這是我的習慣)。
patterns
參數告訴 Ansible 將什麼視為匹配項。 我下載的所有 CSV 文件都以 .csv 結尾,但我確信我也願意刪除 .CSV (全部大寫字母)。
此步驟的最後潤色是調用 register
模組,它將 find
過程的結果保存到名為 result
的變量中。
這很重要,因為我希望 Ansible 對 find
的結果執行第二個操作,因此這些結果需要存儲在某個地方以進行下一步。
使用 Ansible 刪除文件
任務中的下一步是刪除 find
已發現的文件。 用於刪除文件的模組是 file
模組。
此步驟完全依賴於 find
步驟,因此它使用多個變量
- name: Remove CSV files
file:
path: "{{ item.path }}"
state: absent
with_items: "{{ result.files }}"
path
參數使用內建的 "{{ item.path }}"
變量,該變量令人困惑的是實際上尚未定義。 該變量在 file
模組在 with_items
關鍵字的循環中使用之前,沒有關於路徑的信息。 with_items
步驟使用 result
變量的內容一次提取一個文件名,這成為 path
參數的 item
。 一旦提取了當前項目的路徑,Ansible 就使用 state: absent
規則來確保位於該路徑的文件不 留在系統上(換句話說,它被刪除了。)
這是一個非常 危險的步驟,尤其是在測試期間。 如果你在此步驟中出錯,你很容易刪除你不打算刪除的文件。
驗證 playbook
Ansible playbook 是用 YAML 編寫的,它具有嚴格的語法。 使用 yamllint
命令驗證你的 YAML 是否正確
$ yamllint cleanup.yaml
$
沒有結果表示沒有錯誤。 這個 playbook 一定是由真正 了解並熱愛 YAML 的人編寫的!
安全地測試 Ansible playbook
為了避免意外刪除我的整個主目錄,我使用 --check
選項運行了我的第一次嘗試。 這確保 Ansible 實際上不會對你的系統進行更改。
$ ansible-playbook --check example.yaml
[WARNING]: provided hosts list is empty, only localhost is available.
'all'
PLAY [localhost] ****************************************************
TASK [Gathering Facts] **********************************************
ok: [localhost]
TASK [Find CSV files in Downloads] **********************************
ok: [localhost]
TASK [Remove CSV files] *********************************************
changed: [localhost] => (item={'path': '/home/tux/Downloads/foo.csv', [...]
changed: [localhost] => (item={'path': '/home/tux/Downloads/bar.csv', [...]
changed: [localhost] => (item={'path': '/home/tux/Downloads/baz.csv', [...]
PLAY RECAP **********************************************************
localhost : ok=3 changed=1 unreachable=0 [...]
輸出非常冗長,但它表明我的 playbook 是正確的:只有下載中的 CSV 文件被標記為要刪除。
運行 Ansible playbook
要運行 Ansible playbook,你使用 ansible-playbook
命令
$ ansible-playbook example.yaml
確認結果
$ ls *.csv ~/Downloads/
ls: cannot access '*.csv': No such file or directory
/home/tux/Downloads/:
file.txt
排程 Ansible playbook
Ansible playbook 已被確認,但我希望它至少每週運行一次。 我使用 Anacron 而不是 Cron,所以我創建了一個 Anacron 作業來每週運行
$ cat << EOF >> ~/.local/etc/cron.weekly/cleanup
#!/bin/sh
ansible-playbook $HOME/Ansible/cleanup.yaml
EOF
$ chmod +x ~/.local/etc/cron.daily/cleanup
你可以使用 Ansible 做什麼?
通常,Ansible 旨在作為系統維護工具。 它經過微調,可以引導複雜的系統,以幫助在出現問題時進行糾正,並使系統保持在特定狀態。 我已將其用於簡單但重複的任務,例如設置通常需要多個命令或點擊的複雜目錄樹。 我也將其用於我不想做錯的任務,例如從目錄中刪除舊文件。 我也將其用於對我來說太複雜而懶得記住的任務,例如將對生產系統所做的幾個更改與其冗餘備份系統同步。
我不在我的服務器上使用這個清理腳本,因為我不會每週在我的服務器上下載 CSV 文件,但我確實使用了它的變體。 Ansible 不是 shell 或 Python 腳本的替代品,但對於某些任務,它是一種非常精確的方法來執行你可能希望在更多系統上運行的一組任務。
2 條評論