4.Ansible自動化之-部署文件到主機

4 - 部署文件到受管主機

實驗環境

先通過以下命令搭建基礎環境(創建工作目錄、配置 Ansible 環境和主機清單):

# 在控制節點(controller)上創建web目錄并進入,作為工作目錄
[bq@controller ~]$ mkdir web && cd web# 創建Ansible配置文件ansible.cfg,定義連接和權限提升參數
[bq@controller web]$ cat > ansible.cfg <<'EOF'
[defaults]
remote_user = bq    # 默認遠程連接用戶為bq
inventory = ./inventory  # 指定主機清單文件路徑為當前目錄的inventory[privilege_escalation]
become = True           # 允許提權(切換到其他用戶)
become_user = root      # 提權目標用戶為root
become_method = sudo    # 提權方式為sudo
become_ask_pass = False # 提權時不詢問密碼(需提前配置sudo免密)
EOF# 創建主機清單文件inventory,列出需要管理的主機
[bq@controller web]$ cat > inventory <<'EOF'
controller  # 控制節點自身
node1       # 受管節點1
node2       # 受管節點2
node3       # 受管節點3
node4       # 受管節點4
EOF

修改文件并將其復制到主機

Ansible 的 Files 模塊庫包含一系列文件管理工具,能幫我們完成創建文件、復制文件、修改權限等日常 Linux 文件操作。下面逐個介紹常用模塊的用法。

file 模塊:管理文件 / 目錄的屬性(創建、刪除、改權限等)

模塊作用:可以設置文件 / 目錄的權限、所有者、SELinux 上下文等屬性,也能直接創建空文件或目錄,或者刪除不需要的文件 / 目錄(類似 Linux 的touchmkdirrmchmod等命令的組合)。

實驗 1:創建文件并設置權限

實驗流程

  1. 編寫 playbook,定義要創建的文件路徑、所有者、權限等信息;
  2. 執行 playbook,讓 Ansible 在目標主機上執行創建操作;
  3. 登錄受管節點,檢查文件是否創建成功,以及屬性是否符合預期。
---
- hosts: node1        # 目標主機為node1(僅在該節點執行)gather_facts: no    # 不收集主機信息(減少執行時間,加快操作速度)tasks:- name: Touch a file and set permissions  # 任務描述:創建文件并設置權限file:path: /tmp/testfile  # 目標文件的路徑(在node1的/tmp目錄下創建testfile)owner: bq         # 文件的所有者設置為bq用戶group: wheel         # 文件的所屬組設置為wheel組mode: 0640           # 文件權限設置為640(所有者可讀可寫,組內用戶可讀,其他用戶無權限;必須帶前導0,否則會解析錯誤)state: touch         # 狀態為"創建文件"(類似Linux的touch命令,若文件不存在則創建空文件,存在則更新修改時間)

注意:mode參數必須帶前導 0(如0640)或用引號包裹(如'640')。如果直接寫640,Ansible 會當作十進制處理,導致權限計算錯誤(比如變成-w-------T這種不符合預期的權限)。

實驗 2:創建目錄

實驗流程

  1. 編寫 playbook,指定要創建的目錄路徑、所有者、權限等;
  2. 執行 playbook,讓 Ansible 在目標主機上創建目錄;
  3. 登錄受管節點,驗證目錄是否存在,以及所有者、權限是否正確。
---
- hosts: node1gather_facts: notasks:- name: create directory  # 任務描述:創建目錄file:path: /webdev         # 目標目錄路徑(在node1的根目錄下創建webdev目錄)owner: apache         # 目錄所有者設置為apache用戶(通常用于web服務相關目錄)group: apache         # 目錄所屬組設置為apache組mode: 0755            # 目錄權限為755(所有者可讀可寫可執行,組和其他用戶可讀可執行;目錄需要執行權限才能進入)state: directory      # 狀態為"創建目錄"(類似Linux的mkdir命令,若目錄不存在則創建,存在則不做操作)
...                           # YAML文件結尾的省略符號(實際編寫時必須包含)
實驗 3:刪除文件

實驗流程

  1. 編寫 playbook,指定要刪除的文件路徑;
  2. 執行 playbook,讓 Ansible 在目標主機上刪除文件;
  3. 登錄受管節點,確認文件已被刪除。
---
- hosts: node1gather_facts: notasks:- name: delete file  # 任務描述:刪除文件file:path: /tmp/testfile  # 要刪除的文件路徑(node1上的/tmp/testfile)state: absent        # 狀態為"不存在"(即刪除文件,類似Linux的rm命令;若文件不存在則不做操作)
sefcontext 模塊:管理 SELinux 的持久規則

模塊作用:用于在 SELinux 的規則庫中添加或刪除持久規則(類似 Linux 的semanage fcontext命令)。注意:添加的規則不會立即生效,需要通過restorecon等命令重新標注文件后才會應用。

實驗:添加 SELinux 上下文規則

實驗流程

  1. 編寫 playbook,定義要設置的文件路徑和對應的 SELinux 類型;
  2. 執行 playbook,讓 Ansible 在目標主機上添加 SELinux 規則;
  3. (可選)在受管節點執行restorecon命令,使新添加的規則立即生效。
---
- name: 添加SELinux上下文規則hosts: node1tasks:- name: 獲取SElinux當前狀態command: getenforce  # 執行getenforce命令,獲取SELinux當前模式(Enforcing/Permissive)register: selinux_running_state  # 將命令結果保存到變量selinux_running_statechanged_when: false  # 標記該任務不會改變主機狀態(避免Ansible誤判為"已修改")failed_when: false   # 即使命令執行失敗也不標記任務失敗(兼容SELinux未開啟的情況)- name: 僅在Permissive模式下切換為Enforcingcommand: setenforce 1  # 將SELinux切換為強制模式(1表示Enforcing)ignore_errors: no  # 若執行失敗則標記任務失敗(確保SELinux正常運行)- name: 安裝policycoreutils-python依賴yum:  # 使用yum模塊安裝依賴包(SELinux規則管理需要該工具)name: policycoreutils-pythonstate: present  # 確保包已安裝- name: 設置/samba目錄的SELinux上下文sefcontext:target: '/samba(/.*)?'  # 匹配路徑:/samba目錄及所有子目錄和文件(正則表達式)setype: samba_share_t   # 設置SELinux類型為samba_share_t(Samba共享目錄的專用類型)state: present          # 狀態為"存在"(即添加該規則到SELinux規則庫)

注意:sefcontext模塊僅修改 SELinux 的規則庫,不會直接改變現有文件的 SELinux 上下文。如果要讓規則立即生效,需配合file模塊(file模塊會實時應用上下文)或手動執行restorecon -R /samba(遞歸刷新 /samba 目錄的上下文)。

lineinfile 模塊:管理文件中的單行內容

模塊作用:用于修改已存在的文件,可確保文件中存在特定行、替換符合條件的行,或在指定位置插入行(類似 Linux 的sed命令的單行處理功能)。

實驗 1:向文件添加特定行

實驗流程

  1. 編寫 playbook,先創建目標文件,再指定要添加的行內容;
  2. 執行 playbook,讓 Ansible 在目標文件中添加行;
  3. 查看文件內容,驗證行是否添加成功。
---
- hosts: node1gather_facts: notasks:- name: 創建文件file:  # 先創建/tmp/testfile文件(若已存在則不做操作)path: /tmp/testfilestate: touchowner: bqgroup: wheelmode: 0644- name: add line  # 任務描述:添加一行內容lineinfile:path: /tmp/testfile  # 目標文件路徑(node1上的/tmp/testfile)line: 'Add this line to file'  # 要添加的行內容state: present      # 確保該行存在(如果文件中沒有,則添加到末尾;如果已有,則不重復添加)
實驗 2:在指定位置插入行

實驗流程

  1. 編寫 playbook,指定目標文件、要插入的行,以及插入位置(某行之前 / 之后);
  2. 執行 playbook,讓 Ansible 在指定位置插入行;
  3. 查看文件內容,驗證行是否插入到正確位置。
# 在"Listen 80"行之前插入"Listen 82"
---
- hosts: node1gather_facts: notasks:- name: add line before Listen 80lineinfile:path: /etc/httpd/conf/httpd.conf  # 目標文件(httpd服務的配置文件)line: 'Listen 82'                 # 要插入的行(讓httpd監聽82端口)insertbefore: 'Listen 80'         # 插入位置:在"Listen 80"行之前state: present# 在"Listen 80"行之后插入"Listen 82"
---
- hosts: node1gather_facts: notasks:- name: add line after Listen 80lineinfile:path: /etc/httpd/conf/httpd.confline: 'Listen 82'insertafter: 'Listen 80'  # 插入位置:在"Listen 80"行之后state: present
...
實驗 3:替換符合條件的行

實驗流程

  1. 編寫 playbook,用正則表達式匹配要替換的行,指定新內容;
  2. 執行 playbook,讓 Ansible 替換目標行;
  3. 查看文件內容,驗證匹配的行是否被正確替換。
# 替換包含"Add"的行
---
- hosts: node1gather_facts: notasks:- name: replace line  # 任務描述:替換行內容lineinfile:path: /tmp/testfileregexp: 'Add'     # 正則表達式:匹配所有包含"Add"的行line: 'replace'   # 替換后的內容(將匹配的行替換為"replace")state: present# 注釋掉httpd的80端口監聽(在行首加#)
---
- hosts: node1gather_facts: notasks:- name: comment Listen 80lineinfile:path: /etc/httpd/conf/httpd.confline: '#Listen 80'  # 替換后的內容(在原行首加#,實現注釋)regexp: '^Listen 80'  # 正則表達式:匹配以"Listen 80"開頭的行(^表示行首)state: present
...
replace 模塊:批量替換文件中的內容

模塊作用:用正則表達式匹配文件中所有符合條件的內容,并一次性替換(類似 Linux 的sed -i 's/原內容/新內容/g'命令,會替換所有匹配項,而不僅是單行)。

實驗:替換所有匹配的行

實驗流程

  1. 編寫 playbook,定義目標文件、匹配規則(正則表達式)和替換內容;
  2. 執行 playbook,讓 Ansible 批量替換文件內容;
  3. 查看文件內容,驗證所有匹配的內容是否被替換。
---
- hosts: node1gather_facts: notasks:- name: replace multi line  # 任務描述:批量替換行replace:path: /tmp/testfile    # 目標文件(node1上的/tmp/testfile)regexp: '^Hello World.*'  # 正則表達式:匹配所有以"Hello World"開頭的行(.*表示任意字符)replace: 'Hello bq'    # 替換后的內容(將匹配的行替換為"Hello bq")
...
blockinfile 模塊:管理文件中的多行文本塊

模塊作用:向文件中插入、更新或刪除多行文本塊。插入的內容會自動添加標記(# BEGIN ANSIBLE MANAGED BLOCK# END ANSIBLE MANAGED BLOCK),方便后續識別和更新(再次執行時會更新塊內內容,而不是重復添加)。

實驗:向文件添加多行文本塊

實驗流程

  1. 編寫 playbook,定義目標文件和要添加的多行內容;
  2. 執行 playbook,讓 Ansible 在目標文件中插入文本塊;
  3. 查看文件內容,驗證文本塊是否添加,及是否包含自動生成的標記。
---
- hosts: node1gather_facts: notasks:- name: add block lines to file  # 任務描述:添加多行文本塊blockinfile:path: /tmp/testfile          # 目標文件(node1上的/tmp/testfile)block: |                     # 要添加的多行內容(| 表示保留換行符,保持原格式)line 1 in fileline 2 in fileaaline 3 in file sssstate: present               # 確保文本塊存在(若不存在則添加;若已存在則更新內容)
...

執行后,文件中會添加以下內容(自動包含標記):

# BEGIN ANSIBLE MANAGED BLOCK
line 1 in file
line 2 in fileaa
line 3 in file sss
# END ANSIBLE MANAGED BLOCK
stat 模塊:獲取文件的狀態信息

模塊作用:檢索文件的詳細信息(如權限、校驗和、創建時間、大小等),類似 Linux 的stat命令。獲取的結果可以保存到變量中,用于后續任務的條件判斷(比如根據文件是否存在決定是否執行某操作)。

實驗:獲取文件的 MD5 校驗和

實驗流程

  1. 編寫 playbook,用 stat 模塊獲取文件信息并保存到變量;
  2. 執行 playbook,通過 debug 模塊輸出文件的 MD5 校驗和;
  3. 查看輸出結果,驗證是否正確獲取校驗和。
---
- hosts: node1gather_facts: notasks:- stat:  # 調用stat模塊獲取文件信息path: /tmp/testfile        # 目標文件(node1上的/tmp/testfile)checksum_algorithm: md5    # 指定校驗和算法為MD5(可選值:md5、sha1、sha256等)register: result             # 將獲取的信息保存到變量result中- debug:  # 輸出MD5校驗和msg: "/tmp/testfile md5 is {{ result.stat.checksum }}"  # 通過{{ }}引用變量中的checksum值- debug:  # 輸出所有文件信息(方便查看詳細內容,如權限、大小等)var: result  # 直接輸出變量result的內容
...
copy 模塊:復制文件到受管節點

模塊作用:將控制節點或其他遠程節點的文件復制到受管節點,類似 Linux 的scp命令。支持設置文件權限、所有者,以及是否備份原文件、是否強制覆蓋等。

實驗 1:復制控制節點文件到受管節點

實驗流程

  1. 在控制節點準備好要復制的文件(如/tmp/testfile);
  2. 編寫 playbook,指定控制節點的源文件路徑和受管節點的目標路徑;
  3. 執行 playbook,讓 Ansible 完成文件復制;
  4. 在受管節點查看目標路徑,驗證文件是否復制成功。
---
- name: 復制控制節點文件到受管節點hosts: node1  # 目標受管節點tasks:- name: 復制控制節點的/tmp/testfile到受管節點copy:src: /tmp/testfile  # 控制節點上的源文件路徑(可以是絕對路徑,或相對于playbook的相對路徑)dest: /tmp/  # 受管節點上的目標目錄(復制后會保持原文件名,即/tmp/testfile)owner: root  # 可選:設置文件所有者為rootgroup: root  # 可選:設置文件所屬組為rootmode: 0644   # 可選:設置文件權限為644(所有者可讀可寫,組和其他用戶可讀)backup: yes  # 可選:如果目標文件已存在,先創建.bak備份(如/tmp/testfile.bak)- name: 驗證文件是否復制成功stat:  # 檢查受管節點上的目標文件path: /tmp/testfile  # 受管節點上的目標文件路徑register: file_check  # 將檢查結果保存到變量file_check- name: 輸出驗證結果debug:  # 當文件存在時,輸出成功信息msg: "文件已成功復制到受管節點,路徑為: /tmp/testfile"when: file_check.stat.exists  # 條件:僅當file_check.stat.exists為true時執行- name: 查看文件內容(可選)command: cat /tmp/testfile  # 讀取文件內容register: file_content  # 保存內容到變量file_contentwhen: file_check.stat.exists  # 僅當文件存在時執行- name: 顯示文件內容debug:  # 輸出文件內容msg: "文件內容:\n{{ file_content.stdout }}"  # stdout存儲命令執行結果when: file_check.stat.exists  # 僅當文件存在時執行
...

說明:copy模塊默認force: yes(強制覆蓋目標文件),如果設置force: no,則當目標文件已存在時不會覆蓋(保留原文件)。

實驗 2:直接寫入字符串到文件

實驗流程

  1. 編寫 playbook,用content參數定義要寫入的文件內容;
  2. 執行 playbook,讓 Ansible 在受管節點創建文件并寫入內容;
  3. 在受管節點查看文件內容,驗證是否正確。
---
- name: 直接寫入字符串到受管節點的文件hosts: node1tasks:- name: 創建文件并寫入內容copy:content: |  # 要寫入的內容(| 表示保留換行,支持多行)這是第一行內容這是第二行內容可以包含多行字符串最后一行內容dest: /tmp/demo.txt  # 受管節點上的目標文件路徑(會創建該文件)owner: root          # 可選:設置文件所有者為rootgroup: root          # 可選:設置文件所屬組為rootmode: 0644           # 可選:設置文件權限為644- name: 驗證文件內容command: cat /tmp/demo.txt  # 讀取文件內容register: file_content  # 保存內容到變量- name: 顯示文件內容debug:  # 輸出文件內容msg: "文件內容如下:\n{{ file_content.stdout }}"
...
synchronize 模塊:基于 rsync 同步文件 / 目錄

模塊作用:封裝了rsync工具,用于高效同步文件 / 目錄(速度比copy模塊快,適合大量文件或大文件同步)。需要控制節點和受管節點都安裝rsync工具。

實驗 1:同步單個文件

實驗流程

  1. 確保控制節點和受管節點都安裝rsync(可通過yum install -y rsync安裝);
  2. 編寫 playbook,指定控制節點的源文件路徑和受管節點的目標路徑;
  3. 執行 playbook,讓 Ansible 通過 rsync 同步文件;
  4. 在受管節點驗證文件是否同步成功。
---
- name: 使用synchronize模塊同步單個文件hosts: node1  # 受管節點tasks:# 步驟1:確保控制節點和受管節點都安裝rsync- name: 安裝rsync工具yum:name: rsyncstate: present  # 確保rsync已安裝# 步驟2:同步控制節點的文件到受管節點- name: 同步單個文件到受管節點synchronize:src: /path/on/control/node/source.txt  # 控制節點上的源文件路徑(替換為實際路徑)dest: /path/on/remote/node/destination.txt  # 受管節點上的目標路徑(替換為實際路徑)mode: push  # 同步方向:從控制節點推送到受管節點(默認就是push,可省略)# 步驟3:驗證文件是否同步成功- name: 檢查受管節點上的目標文件stat:path: /path/on/remote/node/destination.txt  # 受管節點上的目標文件路徑register: file_status  # 保存檢查結果- name: 顯示驗證結果debug:  # 當文件存在時,輸出成功信息msg: "文件同步成功,路徑:{{ file_status.stat.path }}"when: file_status.stat.exists  # 僅當文件存在時執行
...
實驗 2:同步目錄

實驗流程

  1. 在控制節點準備要同步的目錄(如/etc/sysconfig);
  2. 編寫 playbook,指定控制節點的源目錄和受管節點的目標路徑;
  3. 執行 playbook,讓 Ansible 同步目錄;
  4. 在受管節點查看目標路徑,驗證目錄內容是否同步成功。
---
- hosts: node1gather_facts: noremote_user: root  # 同步系統目錄可能需要root權限tasks:- name: synchronize directory  # 任務描述:同步目錄synchronize:src: /etc/sysconfig  # 控制節點上的源目錄(/etc/sysconfig,包含系統服務配置)dest: /tmp/          # 受管節點上的目標路徑(同步后會在/tmp下創建sysconfig子目錄,即/tmp/sysconfig)
...
fetch 模塊:從受管節點獲取文件到控制節點

模塊作用:將受管節點的文件復制到控制節點,常用于收集日志、配置文件等。文件會按 “控制節點目標路徑 / 受管節點名 / 原文件路徑” 的結構保存(方便區分不同節點的文件)。

實驗:從受管節點獲取文件

實驗流程

  1. 編寫 playbook,指定受管節點的源文件路徑和控制節點的保存路徑;
  2. 執行 playbook,讓 Ansible 從受管節點復制文件到控制節點;
  3. 在控制節點查看保存路徑,驗證文件是否按預期結構保存。
---
- hosts: node1gather_facts: notasks:- name: fetch file from remote node  # 任務描述:獲取遠程文件fetch:src: /tmp/testfile  # 受管節點上的源文件路徑(node1的/tmp/testfile)dest: /tmp          # 控制節點上的保存路徑
...

執行后,文件會保存在控制節點的/tmp/node1/tmp/testfile(路徑結構:目標路徑/受管節點名/原文件絕對路徑)。

使用 JINJA2 模板部署文件

Jinja2 模板是一種帶變量和邏輯的文件(比如包含{{ 變量 }}{% 循環/條件 %}等)。通過 Ansible 的template模塊部署到受管節點時,Ansible 會自動替換變量、執行邏輯,生成個性化的配置文件。

基礎示例:部署動態網頁

實驗流程

  1. 創建 Jinja2 模板文件(包含變量,如{{ ansible_fqdn }});
  2. 編寫 playbook,用template模塊部署模板到受管節點;
  3. 執行 playbook,在受管節點查看生成的文件,驗證變量是否被正確替換。
步驟 1:編寫 playbook(deploy_web.yml
---
- name: Enable intranet services  # 部署web服務hosts: node1tasks:- name: ensure latest version of httpd  # 安裝httpd服務(用于提供web服務)yum:name: httpdstate: latest  # 確保安裝最新版本- name: deploy test html page  # 部署動態主頁template:src: index.html.j2  # 控制節點上的Jinja2模板文件(與playbook同目錄)dest: /var/www/html/index.html  # 受管節點上的目標文件(httpd的默認主頁路徑)- name: start and enable httpd  # 啟動httpd并設置開機自啟service:name: httpdenabled: true  # 開機自啟state: restarted  # 重啟服務(使配置生效)
步驟 2:創建模板文件(index.html.j2

在 playbook 同目錄下創建index.html.j2,內容如下:

Welcome to {{ ansible_fqdn }}  # {{ }} 中的變量會被替換為受管節點的完全主機名(如node1.bq.cloud)
步驟 3:執行與驗證

執行 playbook 后,受管節點的/var/www/html/index.html內容會自動替換變量,變成:

Welcome to node1.bq.cloud  # 假設node1的完全主機名是node1.bq.cloud
進階示例:部署 SSH 配置文件

實驗流程

  1. 創建含多個變量的 Jinja2 模板(如{{ ssh_port }}{{ root_allowed }});
  2. 在 playbook 中定義模板變量的值;
  3. 部署模板到受管節點,驗證生成的配置文件是否正確替換變量。
步驟 1:編寫模板(sshd_config.j2
# {{ ansible_managed }}  # 會替換為"Ansible managed"(可在ansible.cfg中自定義)
# DO NOT MAKE LOCAL MODIFICATIONS TO THIS FILE AS THEY WILL BE LOST
Port {{ ssh_port }}  # SSH端口(使用變量ssh_port的值)
ListenAddress {{ ansible_facts['default_ipv4']['address'] }}  # 監聽IP(使用受管節點的默認IPv4地址)HostKey /etc/ssh/ssh_host_rsa_key  
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
PermitRootLogin  {{ root_allowed }}  # 是否允許root登錄(使用變量root_allowed的值)
AllowGroups {{ groups_allowed }}  # 允許登錄的組(使用變量groups_allowed的值)AuthorizedKeysFile      /etc/.rht_authorized_keys .ssh/authorized_keys
PasswordAuthentication {{ passwords_allowed }}  # 是否允許密碼認證(使用變量passwords_allowed的值)
步驟 2:編寫 playbook(deploy_ssh.yml
---
- name: config sshd service  # 配置SSH服務hosts: node1vars:  # 定義模板中用到的變量(鍵值對形式)ssh_port: 1022  # SSH端口設為1022(非默認端口更安全)root_allowed: "yes"  # 允許root登錄groups_allowed: wheel  # 允許wheel組用戶登錄passwords_allowed: "yes"  # 允許密碼認證ansible_managed: "Ansible managed: do not edit manually"  # 覆蓋默認的ansible_managed變量tasks:- name: deploy sshd config  # 部署模板template:src: sshd_config.j2  # 控制節點上的模板文件dest: /root/sshd_config  # 先部署到/root目錄驗證(實際使用時應替換為/etc/ssh/sshd_config)
Jinja2 模板語法詳解

模板中通過特殊符號包裹變量和邏輯,常用符號:

  • {{ 變量/表達式 }}:輸出變量或表達式結果(如{{ 1+1 }}輸出2);
  • {% 控制語句 %}:用于循環(for)、條件判斷(if)等(如{% for user in users %});
  • {# 注釋 #}:模板內的注釋,不會出現在生成的文件中(僅用于模板編寫者參考)。
1. for 循環:遍歷列表 / 字典

作用:重復輸出列表或字典中的每個元素,類似編程語言中的for循環。

示例 1:遍歷用戶列表
  • playbook 中定義變量:

    vars:users:  # 定義一個用戶列表- tom- jack- Snoopy- lucy
    
  • 模板文件(testfile.j2):

    {% for user in users %}  # 遍歷users列表,每次取一個元素賦值給user
    {{ user }}  # 輸出當前user的值
    {% endfor %}  # 結束循環
    
  • 生成的文件內容:

    tom
    jack
    Snoopy
    lucy
    
示例 2:帶索引的循環
  • 模板文件(testfile.j2):

    {% for user in users %}
    {{ loop.index }} - {{ user }}  # loop.index是循環的序號(從1開始)
    {% endfor %}
    
  • 生成的文件內容:

    1 - tom
    2 - jack
    3 - Snoopy
    4 - lucy
    
示例 3:生成主機列表文件

需求:在/etc/myhosts中添加所有主機的 IP、完全主機名和主機名。

  • 主機清單(inventory):

    [controllers]
    controller[dev]
    node1[test]
    node2[prod]
    node3
    node4
    
  • playbook(deploy_hosts.yml):

    ---
    - name: deploy /etc/myhostshosts: all  # 必須對所有主機執行,才能收集所有主機的信息tasks:- name: generate /etc/myhoststemplate:src: hosts.j2dest: /etc/myhostswhen: inventory_hostname in groups.dev  # 只部署到dev組主機(這里指node1)
    ...
    
  • 模板文件(hosts.j2):

    127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1 localhost localhost.localdomain localhost6 localhost6.localdomain6{% for server in groups.all %}   # 遍歷所有主機(groups.all是包含所有主機的列表)
    # hostvars[server]               # 用于獲取其他主機的信息(如IP、主機名)
    {{ hostvars[server].ansible_default_ipv4.address }} {{ hostvars[server].ansible_fqdn }} {{ hostvars[server].ansible_hostname }}
    {% endfor %}
    
2. if 條件判斷:根據條件輸出內容

作用:滿足條件時才輸出特定內容,類似if-else語句。

示例 1:判斷變量是否存在
{% if PORT is defined %}  # 如果PORT變量已定義(在playbook中設置過)
bind-address=0.0.0.0:{{ PORT }}  # 使用PORT變量的值(如0.0.0.0:3307)
{% else %}  # 否則(PORT未定義)
bind-address=0.0.0.0:3306  # 使用默認端口3306
{% endif %}
示例 2:循環中過濾元素
{% for num in [7,1,5,3,9] if num>3 %}  # 只遍歷大于3的數字(過濾條件)
{{ num }}
{% endfor %}

生成的文件內容:

7
5
9
3. 表達式:支持運算和比較
比較運算
{{ 1 == 1 }}  # 等于 → True
{{ 2 != 2 }}  # 不等于 → False
{{ 2 > 1 }}   # 大于 → True
{{ 2 <= 1 }}  # 小于等于 → False
邏輯運算
{{ (2 > 1) or (1 > 2) }}  # 或 → True(只要一個條件成立)
{{ (2 > 1) and (1 > 2) }} # 與 → False(兩個條件都成立才為True)
{{ not true }}  # 非 → False(取反)
算術運算
{{ 3 + 2 }}   # 加 → 5
{{ 3 * 5 }}   # 乘 → 15
{{ 2 **3 }}  # 冪 → 8(2的3次方)
{{ 7 // 5 }}  # 整除 → 1(只保留整數部分)
{{ 17 % 5 }}  # 取余 → 2(17除以5的余數)
4. 過濾器:格式化輸出結果

過濾器用于對變量或表達式的結果進行處理(如轉換大小寫、排序等),格式為{{ 變量 | 過濾器 }}

字符串處理
{{ 'hello' | upper }}  # 轉大寫 → HELLO
{{ 'HELLO' | lower }}  # 轉小寫 → hello
{{ 'hello' | capitalize }}  # 首字母大寫 → Hello
{{ '  hello  ' | trim }}  # 去除首尾空格 → hello
列表處理
{{ [3,1,7] | sort }}  # 升序排序 → [1, 3, 7]
{{ [3,1,7] | max }}   # 最大值 → 7
{{ [3,1,7] | sum }}   # 求和 → 11
{{ [3,1,7] | join(',') }}  # 用逗號連接 → 3,1,7
數字處理
{{ '123' | int }}  # 轉整數 → 123(將字符串轉為整數)
{{ 'abc' | int(default=0) }}  # 轉換失敗用默認值 → 0(字符串無法轉整數時返回0)
{{ 12.5 | round }}  # 四舍五入 → 13
{{ -5 | abs }}  # 絕對值 → 5
ansible_managed 變量

用于在模板中添加 “此文件由 Ansible 管理” 的注釋,提醒用戶不要手動修改(否則下次執行 playbook 可能被覆蓋)。默認值在ansible.cfg中定義:

[defaults]
ansible_managed = Ansible managed  # 可自定義,如"Ansible managed: do not edit manually"

在模板中引用:

# {{ ansible_managed }}  # 會替換為上述配置的值(如"Ansible managed: do not edit manually")

如涉及版權問題請聯系作者處理!!!!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/93683.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93683.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93683.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Vuex的使用

Vuex 超詳細使用教程&#xff08;從入門到精通&#xff09;一、Vuex 是什么&#xff1f;Vuex 是專門為 Vue.js 設計的狀態管理庫&#xff0c;它采用集中式存儲管理應用的所有組件的狀態。簡單來說&#xff0c;Vuex 就是一個"全局變量倉庫"&#xff0c;所有組件都可以…

pytorch 數據預處理,加載,訓練,可視化流程

流程定義自定義數據集類定義訓練和驗證的數據增強定義模型、損失函數和優化器訓練循環&#xff0c;包括驗證訓練可視化整個流程模型評估高級功能擴展混合精度訓練?分布式訓練?{:width“50%” height“50%”} 定義自定義數據集類 # #1. 自定義數據集類 # class CustomImageD…

Prompt工程:OCR+LLM文檔處理的精準制導系統

在PDF OCR與大模型結合的實際應用中&#xff0c;很多團隊會發現一個現象&#xff1a;同樣的OCR文本&#xff0c;不同的Prompt設計會產生截然不同的提取效果。有時候準確率能達到95%&#xff0c;有時候卻只有60%。這背后的關鍵就在于Prompt工程的精細化程度。 &#x1f3af; 為什…

RecSys:粗排模型和精排特征體系

粗排 在推薦系統鏈路中&#xff0c;排序階段至關重要&#xff0c;通常分為召回、粗排和精排三個環節。粗排作為精排前的預處理階段&#xff0c;需要在效果和性能之間取得平衡。 雙塔模型 后期融合&#xff1a;把用戶、物品特征分別輸入不同的神經網絡&#xff0c;不對用戶、…

spring聲明式事務,finally 中return對事務回滾的影響

finally 塊中使用 return 是一個常見的編程錯誤&#xff0c;它會&#xff1a; 跳過正常的事務提交流程。吞掉異常&#xff0c;使錯誤處理失效 導致不可預測的事務行為Java 中 finally 和 return 的執行機制&#xff1a;1. finally 塊的基本特性 在 Java 中&#xff0c;finally …

WPF 打印報告圖片大小的自適應(含完整示例與詳解)

目標&#xff1a;在 FlowDocument 報告里&#xff0c;根據 1~6 張圖片的數量&#xff0c; 自動選擇 2 行 3 列 的最佳布局&#xff1b;在只有 1、2、4 張時保持“占滿感”&#xff0c;打印清晰且不變形。規則一覽&#xff1a;1 張 → 占滿 23&#xff08;大圖居中&#xff09;…

【AI大模型前沿】百度飛槳PaddleOCR 3.0開源發布,支持多語言、手寫體識別,賦能智能文檔處理

系列篇章&#x1f4a5; No.文章1【AI大模型前沿】深度剖析瑞智病理大模型 RuiPath&#xff1a;如何革新癌癥病理診斷技術2【AI大模型前沿】清華大學 CLAMP-3&#xff1a;多模態技術引領音樂檢索新潮流3【AI大模型前沿】浙大攜手阿里推出HealthGPT&#xff1a;醫學視覺語言大模…

迅為RK3588開發板Android12 制作使用系統簽名

在 Android 源碼 build/make/target/product/security/下存放著簽名文件&#xff0c;如下所示&#xff1a;將北京迅為提供的 keytool 工具拷貝到 ubuntu 中&#xff0c;然后將 Android11 或 Android12 源碼build/make/target/product/security/下的 platform.pk8 platform.x509…

Day08 Go語言學習

1.安裝Go和Goland 2.新建demo項目實踐語法并使用git實踐版本控制操作 2.1 Goland配置 路徑**&#xff1a;** GOPATH workspace GOROOT golang 文件夾&#xff1a; bin 編譯后的可執行文件 pkg 編譯后的包文件 src 源文件 遇到問題1&#xff1a;運行 ‘go build awesomeProject…

Linux-文件創建拷貝刪除剪切

文章目錄Linux文件相關命令ls通配符含義touch 創建文件命令示例cp 拷貝文件rm 刪除文件mv剪切文件Linux文件相關命令 ls ls是英文單詞list的簡寫&#xff0c;其功能為列出目錄的內容&#xff0c;是用戶最常用的命令之一&#xff0c;它類似于DOS下的dir命令。 Linux文件或者目…

RabbitMQ:交換機(Exchange)

目錄一、概述二、Direct Exchange &#xff08;直連型交換機&#xff09;三、Fanout Exchange&#xff08;扇型交換機&#xff09;四、Topic Exchange&#xff08;主題交換機&#xff09;五、Header Exchange&#xff08;頭交換機&#xff09;六、Default Exchange&#xff08;…

【實時Linux實戰系列】基于實時Linux的物聯網系統設計

隨著物聯網&#xff08;IoT&#xff09;技術的飛速發展&#xff0c;越來越多的設備被連接到互聯網&#xff0c;形成了一個龐大而復雜的網絡。這些設備從簡單的傳感器到復雜的工業控制系統&#xff0c;都在實時地產生和交換數據。實時Linux作為一種強大的操作系統&#xff0c;為…

第五天~提取Arxml中描述信息New_CanCluster--Expert

?? ARXML描述信息提取:挖掘汽車電子設計的"知識寶藏" 在AUTOSAR工程中,描述信息如同埋藏在ARXML文件中的金礦,而New_CanCluster--Expert正是打開這座寶藏的密鑰。本文將帶您深度探索ARXML描述信息的提取藝術,解鎖汽車電子設計的核心知識資產! ?? 為什么描述…

開源 C++ QT Widget 開發(一)工程文件結構

文章的目的為了記錄使用C 進行QT Widget 開發學習的經歷。臨時學習&#xff0c;完成app的開發。開發流程和要點有些記憶模糊&#xff0c;趕緊記錄&#xff0c;防止忘記。 相關鏈接&#xff1a; 開源 C QT Widget 開發&#xff08;一&#xff09;工程文件結構-CSDN博客 開源 C…

手寫C++ string類實現詳解

類定義cppnamespace ym {class string {private:char* _str; // 字符串數據size_t _size; // 當前字符串長度size_t _capacity; // 當前分配的內存容量static const size_t npos -1; // 特殊值&#xff0c;表示最大可能位置public:// 構造函數和析構函數string(…

C++信息學奧賽一本通-第一部分-基礎一-第3章-第2節

C信息學奧賽一本通-第一部分-基礎一-第3章-第2節 2057 星期幾 #include <iostream>using namespace std;int main() {int day; cin >> day;switch (day) {case 1:cout << "Monday";break;case 2:cout << "Tuesday";break;case 3:c…

【leetcode 3】最長連續序列 (Longest Consecutive Sequence) - 解題思路 + Golang實現

最長連續序列 (Longest Consecutive Sequence) - LeetCode 題解 題目描述 給定一個未排序的整數數組 nums&#xff0c;找出數字連續的最長序列&#xff08;不要求序列元素在原數組中連續&#xff09;的長度。要求設計并實現時間復雜度為 O(n) 的算法解決此問題。 示例 1&#x…

礦物分類系統開發筆記(一):數據預處理

目錄 一、數據基礎與預處理目標 二、具體預處理步驟及代碼解析 2.1 數據加載與初步清洗 2.2 標簽編碼 2.3 缺失值處理 &#xff08;1&#xff09;刪除含缺失值的樣本 &#xff08;2&#xff09;按類別均值填充 &#xff08;3&#xff09;按類別中位數填充 &#xff08;…

《UE5_C++多人TPS完整教程》學習筆記43 ——《P44 奔跑混合空間(Running Blending Space)》

本文為B站系列教學視頻 《UE5_C多人TPS完整教程》 —— 《P44 奔跑混合空間&#xff08;Running Blending Space&#xff09;》 的學習筆記&#xff0c;該系列教學視頻為計算機工程師、程序員、游戲開發者、作家&#xff08;Engineer, Programmer, Game Developer, Author&…

TensorRT-LLM.V1.1.0rc1:Dockerfile.multi文件解讀

一、TensorRT-LLM有三種安裝方式&#xff0c;從簡單到難 1.NGC上的預構建發布容器進行部署,見《tensorrt-llm0.20.0離線部署DeepSeek-R1-Distill-Qwen-32B》。 2.通過pip進行部署。 3.從源頭構建再部署&#xff0c;《TensorRT-LLM.V1.1.0rc0:在無 GitHub 訪問權限的服務器上編…