IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 处理程序、任务失败、在被管理节点上创建文件或目录 -> 正文阅读

[系统运维]处理程序、任务失败、在被管理节点上创建文件或目录

处理程序、任务失败、在被管理节点上创建文件或目录

1.测试多个条件

一个when语句可用于评估多个条件。使用andor关键字组合条件,并使用括号分组条件。

如果任一条件为真时满足条件语句,则应当使用or语句。例如,如果计算机上运行的是红帽企业linux或Fedora,则下述条件得到满足:

[root@node1 ansible]# cat node/test.yml 
---
- name: fhaharh
  hosts: 192.168.100.147
  gather_facts: yes
  vars:
    supported_distros: 
      - redhat
      - centos
  tasks: 
    - name: install httpd
      yum: 
         name: httpd
         state: present
      when: >
         ansible_distribution == "CentOS" or
         ansible_distribution == "RedHat"  
[root@node1 ansible]# 


[root@node1 ansible]# ansible-playbook node/test.yml 

PLAY [fhaharh] *****************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [install httpd] ***********************************************************
changed: [192.168.100.147]

PLAY RECAP *********************************************************************
192.168.100.147            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@node1 ansible]# 

使用and运算时,两个条件都必须为真,才能满足整个条件语句。例如,如果远程主机是红帽企业Linux7.5主机,并且安装的内核是指定版本,则将满足以下条件:

[root@node1 ansible]# cat node/test.yml 
---
- name: fhaharh
  hosts: 192.168.100.147
  gather_facts: yes
  vars:
    supported_distros: 
      - redhat
      - centos
  tasks: 
    - name: install httpd
      yum: 
         name: httpd
         state: present
      when: >
         ansible_distribution_version == "7.5" and
         ansible_kernel == "3.10.0-327.el7.x86_64"
[root@node1 ansible]# 



[root@node1 ansible]# ansible-playbook node/test.yml 

PLAY [fhaharh] *****************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [install httpd] ***********************************************************
skipping: [192.168.100.147]

PLAY RECAP *********************************************************************
192.168.100.147            : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0 

? when关键字还支持使用列表来描述条件列表。向when关键字提供列表时,将使用and运算组合所有条件。下面的示例演示了使用and运算符组合多个条件语句的另一方式:

when:
  - ansible_distribution_version == "7.5"
  - ansible_kernel == "3.10.0-327.el7.x86_64"

? 这种格式提高了可读性,而可读性是良好编写Ansible Playbook的关键目标。

通过使用括号分组条件,可以表达更复杂的条件语句。例如,如果计算机上运行的是红帽企业Linux7或Fedora28,则下述条件语句得到满足。此示例使用大于字符,这样长条件就可以在playbook中分成多行,以便于阅读。

when: >
  ( ansible_distribution == "Redhat" and
    ansible_distribution_major_version == "7" )
  or
  ( ansible_distribution == "Fedora" and
    ansible_distribution_major_version == "28" )

2.组合循环和有条件任务

注意:循环和条件可以组合使用

在下例中,yum模块将安装mariadb-server软件包,只要/上挂载的文件系统具有超过300MB的可用空间。ansible_mounts事实是一组字典,各自代表一个已挂载文件系统的相关事实。循环迭代列表中每一字典,只有找到了代表两个条件都为真的已挂载文件系统的字典时,条件语句才得到满足。

[root@node1 ansible]# cat node/host.yml 
---
- hosts: 192.168.100.147
  gather_facts: yes
  tasks: 
    - name: install mariadb-server
      yum: 
        name: mariadb-server
        state: latest
      loop: "{{ ansible_mounts }}"
      when: item.mount == "/" and item.size_available > 300000000
[root@node1 ansible]# 



[root@node1 ansible]# ansible-playbook node/host.yml 

PLAY [192.168.100.147] *********************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [install mariadb-server]      //这里没有报错, 已经执行成功   **************************************************
changed: [192.168.100.147] => (item={'mount': '/', 'device': '/dev/mapper/cs-root', 'fstype': 'xfs', 'options': 'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota', 'size_total': 68551770112, 'size_available': 66409570304, 'block_size': 4096, 'block_total': 16736272, 'block_available': 16213274, 'block_used': 522998, 'inode_total': 33488896, 'inode_available': 33447343, 'inode_used': 41553, 'uuid': 'd0be6eae-d7c5-480d-b875-85a2be711534'})
skipping: [192.168.100.147] => (item={'mount': '/home', 'device': '/dev/mapper/cs-home', 'fstype': 'xfs', 'options': 'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota', 'size_total': 33466781696, 'size_available': 33199591424, 'block_size': 4096, 'block_total': 8170601, 'block_available': 8105369, 'block_used': 65232, 'inode_total': 16349184, 'inode_available': 16349181, 'inode_used': 3, 'uuid': '29988f88-dacd-4bec-ba15-a2ad77492b02'}) 
skipping: [192.168.100.147] => (item={'mount': '/boot', 'device': '/dev/sda1', 'fstype': 'xfs', 'options': 'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota', 'size_total': 1063256064, 'size_available': 859344896, 'block_size': 4096, 'block_total': 259584, 'block_available': 209801, 'block_used': 49783, 'inode_total': 524288, 'inode_available': 523986, 'inode_used': 302, 'uuid': '52eecd3e-b464-4f61-8c00-2d88f1533466'}) 

PLAY RECAP *********************************************************************
192.168.100.147            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[root@node1 ansible]# 

对某个任务结合使用whenloop时,将对每个项检查when语句。

下面是组合使用条件和注册变量的另一个示例。

[root@node1 ansible]# cat node/group.yml 
---
- name: fhlknaf
  hosts: 192.168.100.147
  tasks: 
    - name: gkanfl
      command: /usr/bin/systemctl is-active postfix   //Postfix是否在运行?
      ignore_errors: yes   //如果它不在运行并且命令失败,则不停止处理。
      register: result     //将模块的结果信息保存在名为result的变量中
    - name: fjpsjtmgsm
      service: 
        name: httpd
        state: restarted    //评估Postfix任务的输出。如果systemctl命令的退出代码为0
      when: result.rc == 0   //则Postfix激活并且此任务重启httpd服务
[root@node1 ansible]# 


[root@node1 ansible]# ansible-playbook node/group.yml 

PLAY [fhlknaf] *****************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [gkanfl] ******************************************************************
fatal: [192.168.100.147]: FAILED! => {"changed": true, "cmd": ["/usr/bin/systemctl", "is-active", "postfix"], "delta": "0:00:00.008155", "end": "2021-07-26 09:16:25.058957", "msg": "non-zero return code", "rc": 3, "start": "2021-07-26 09:16:25.050802", "stderr": "", "stderr_lines": [], "stdout": "inactive", "stdout_lines": ["inactive"]}
...ignoring      //在这里运行失败,但是没有停止运行
TASK [fjpsjtmgsm] **************************************************************
skipping: [192.168.100.147]

PLAY RECAP *********************************************************************
192.168.100.147            : ok=2    changed=1    unreachable=0    failed=0    skipped=1    rescued=0    ignored=1   

3.ansible处理程序

Ansible模块设计为具有幂等性。这表示,在正确编写的playbook中,playbook及其任务可以运行多次而不会改变受管主机,除非需要进行更改使受管主机进入所需的状态。

但在时候,在任务确实更改系统时,可能需要运行进一步的任务。例如,更改服务配置文件时可能要求重新加载该服务以便使其更改的配置生效。

处理程序是响应由其他任务触发的通知的任务。仅当任务在受管主机上更改了某些内容时,任务才通知其处理程序。每个处理程序具有全局唯一的名称,在playbook中任务块的末尾触发。如果没有任务通过名称通知处理程序,处理程序就不会运行。如果一个或多个任务通知处理程序,处理程序就会在play中的所有其他任务完成后运行一次。因为处理程序就是任务,所以可以在处理程序中使用他们将用于任何其他任务的模块。通常而言,处理程序被用于重新引导主机和重启服务。

处理程序可视为非活动任务,只有在使用notify语句显式调用时才会被触发。在下列代码片段中,只有配置文件更新并且通知了该任务,restart apache处理程序才会重启Apache服务器:

例子:比如受管主机有httpd服务,然后我们修改它

[root@localhost conf.d]# find / -name *vhosts.conf     //进入找到文件地址
/usr/share/doc/httpd/httpd-vhosts.conf

[root@node1 node]# scp 192.168.100.147:/usr/share/doc/httpd/httpd-vhosts.conf .    //我们把受管主机上的文件复制到当前目录里面来
httpd-vhosts.c 100% 1477   984.4KB/s   00:00    
[root@node1 node]# ls
group.yml  host.yml  httpd-vhosts.conf  test.yml

[root@node1 node]# vim httpd-vhosts.conf    //进入配置文件
<VirtualHost *:80>  
    DocumentRoot "/var/www/html/shen"     
    ServerName server.example.com    //随便给一个名字
</VirtualHost>

[root@localhost ~]# cd /var/www/html
[root@localhost html]# ls
[root@localhost html]# mkdir -p shen    //我们得到受管主机上创建一个,然后往里面写内容
[root@localhost html]# echo "shunzi chishi" > /var/www/html/shen/index.php

[root@node1 ansible]# cat httpd.yml    //playbook编写
---
- hosts: 192.168.100.147
  tasks: 
    - name: install apache
      yum: 
        name: httpd
        state: present
    - name: config httpd
      copy: 
        src: node/httpd-vhosts.conf
        dest: /etc/httpd/conf.d/shunzi.conf
    - name: service httpd
      service: 
        name: httpd
        state: started
        enabled: yes
[root@node1 ansible]# 

[root@node1 ansible]# ansible-playbook httpd.yml   //执行成功
 
PLAY [192.168.100.147] *********************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [install apache] **********************************************************
ok: [192.168.100.147]

TASK [config httpd] ************************************************************
changed: [192.168.100.147]

TASK [service httpd] ***********************************************************
changed: [192.168.100.147]

PLAY RECAP *********************************************************************
192.168.100.147            : ok=4    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  


[root@localhost conf.d]# ls
autoindex.conf  shunzi.conf   //我们创建的文件名已经过来了  welcome.conf
README          userdir.conf
[root@localhost conf.d]# 

在上面的例子中,restart apache处理程序只有在template任务通知已发生更改时才会触发。一个任务可以在其notify部分中调用多个处理程序。Ansible将notify语句视为数组,并且迭代处理程序名称:

[root@node1 ansible]# cat httpd.yml   
---
- hosts: 192.168.100.147
  tasks: 
    - name: install apache
      yum: 
        name: httpd
        state: present
    - name: config httpd
      copy: 
        src: node/httpd-vhosts.conf
        dest: /etc/httpd/conf.d/shunzi.conf
    - name: service httpd
      service: 
        name: httpd
        state: started
        enabled: yes

4.使用处理程序的好处

使用处理程序时需要牢记几个重要事项

  • 处理程序始终按照playhandlers部分指定的顺序运行。它们不按在任务中由notify语句列出的顺序运行,或按任务通知它们的顺序运行。
  • 处理程序通常在相关play中的所有其他任务完成后运行。playbooktasks部分中某一任务调用的处理程序,将等到tasks下的所有任务都已处理后才会运行。
  • 处理程序名称存在于各play命名空间中。如果两个处理程序被错误地给予相同的名称,则仅会运行一个。
  • 即使有多个任务通知处理程序,该处理程序依然仅运行一次。如果没有任务通知处理程序,它就不会运行。
  • 如果包含notify语句的任务没有报告changed结果(例如,软件包已安装并且任务报告ok),则处理程序不会获得通知。处理程序将被跳过,直到有其他任务通知它。只有相关任务报告了changed状态,Ansible才会通知处理程序。

处理程序用于在任务对受管主机进行更改时执行额外操作。它们不应用作正常任务的替代。

5.处理任务失败

Ansible评估任务的返回代码,从而确定任务是成功还是失败。通常而言,当任务失败时,Ansible将立即在该主机上中止play的其余部分并且跳过所有后续任务。

但有些时候,可能希望即使在任务失败时也继续执行play。例如,或许预期待定任务有可能会失败,并且希望通过有条件地运行某项其他任务来修复。

Ansible有多种功能可用于管理任务错误。

默认情况下,任务失败时play会中止。不过,可以通过忽略失败的任务来覆盖此行为。可以在任务中使用ignore_errors关键字来实现此目的。

下列代码片段演示了如何在任务中使用ignore_errors,以便在任务失败时也继续在主机上执行playbook。例如,如果notapkg软件包不存在,则yum模块将失败,但若将ignore_errors设为yes,则执行将继续。

[root@node1 ansible]# cat httpd.yml   //借助上面的yml来操作
---
- hosts: 192.168.100.147
  tasks: 
    - name: install apache
      yum: 
        name: httpd123    //在这安装一个不存在的服务,默认百分百会报错,然后终止后面的任务,不在执行
        state: present
    - name: config httpd
      copy: 
        src: node/httpd-vhosts.conf
        dest: /etc/httpd/conf.d/shunzi.conf
    - name: service httpd
      service: 
        name: httpd
        state: started
        enabled: yes
[root@node1 ansible]# 


[root@node1 ansible]# cat httpd.yml 
---
- hosts: 192.168.100.147
  tasks: 
    - name: install apache
      yum: 
        name: httpd123
        state: present
      ignore_errors: yes      //我们使用这个以便任务失败也能继续执行
    - name: config httpd
      copy: 
        src: node/httpd-vhosts.conf
        dest: /etc/httpd/conf.d/shunzi.conf
    - name: service httpd
      service: 
        name: httpd
        state: started
        enabled: yes
[root@node1 ansible]# 

[root@node1 ansible]# ansible-playbook httpd.yml    //任务失败了后面依然执行
 
PLAY [192.168.100.147] *********************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [install apache] **********************************************************
fatal: [192.168.100.147]: FAILED! => {"changed": false, "failures": ["httpd123 未找到匹配的参数: httpd123"], "msg": "Failed to install some of the specified packages", "rc": 1, "results": []}
...ignoring

TASK [config httpd] ************************************************************
ok: [192.168.100.147]

TASK [service httpd] ***********************************************************
ok: [192.168.100.147]

PLAY RECAP *********************************************************************
192.168.100.147            : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1   

[root@node1 ansible]# 

6.任务失败后强制执行处理 程序

通常而言,如果任务失败并且play在该主机上中止,则收到play中早前任务通知的处理程序将不会运行。如果在play中设置force_handlers: yes关键字,则即使play因为后续任务失败而中止也会调用被通知的处理程序。

下列代码片段演示了如何在play中使用force_handlers关键字,以便在任务失败时也强制执行相应的处理程序:

---
- hosts: 172.16.103.129
  force_handlers: yes
  tasks:
    - name: bbbb
      command: /bin/true
      notify: restart the database
      
    - name: aaaaa
      yum:
        name: notapkg
        state: latest
        
  handlers:
    - name: restart the database
      service:
        name: mariadb
        state: restarted

请记住,处理程序会在任务报告changed结果时获得通知,而在任务报告okfailed结果时不会获得通知。

7.指定任务失败条件

可以在任务中使用failed_when关键字来指定表示任务已失败的条件。这通常与命令模块搭配使用,这些模块可能成功执行了某一命令,但命令的输出可能指示了失败。

例如,可以运行输出错误消息的脚本,并使用该消息定义任务的失败状态。下列代码片段演示了如何在任务中使用failed_when关键字:

[root@localhost opt]# cat shen.sh     //在受管主机写上一个创建用户的脚本。
#! /bin/bash

useradd shen
echo "1" | passwd --stdin shen


[root@node1 ansible]# cat node/test.yml    //控制机中的play写法
---
- name: create user
  hosts: 192.168.100.147
  tasks: 
    - name: test
      command: /opt/shen.sh     //用command模块执行对面路径的脚本
      register: long      
    - debug: 
        var: long     //打印出来
[root@node1 ansible]# 


[root@node1 ansible]# ansible-playbook node/test.yml 

PLAY [create user] *************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [test] ********************************************************************
changed: [192.168.100.147]

TASK [debug] *******************************************************************
ok: [192.168.100.147] => {
    "long": {
        "changed": true,
        "cmd": [
            "/opt/shen.sh"
        ],
        "delta": "0:00:00.025363",
        "end": "2021-07-26 10:21:24.185611",
        "failed": false,
        "rc": 0,
        "start": "2021-07-26 10:21:24.160248",
        "stderr": "useradd:用户“shen”已存在",
        "stderr_lines": [
            "useradd:用户“shen”已存在"
        ],
        "stdout": "更改用户 shen 的密码 。\npasswd:所有的身份验证令牌已经成功更新。",
        "stdout_lines": [
            "更改用户 shen 的密码 。",
            "passwd:所有的身份验证令牌已经成功更新。"
        ]
    }
}

PLAY RECAP *********************************************************************
192.168.100.147            : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  

[root@node1 ansible]# cat node/test.yml     //指定任务失败
---
- name: create user
  hosts: 192.168.100.147
  tasks: 
    - name: test
      command: /opt/shen.sh
      register: long
      failed_when: "'useradd' in long.stderr"
[root@node1 ansible]# 


[root@node1 ansible]# ansible-playbook node/test.yml   //执行失败

PLAY [create user] *************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [test] ********************************************************************
fatal: [192.168.100.147]: FAILED! => {"changed": true, "cmd": ["/opt/shen.sh"], "delta": "0:00:00.025878", "end": "2021-07-26 10:29:34.408988", "failed_when_result": true, "rc": 0, "start": "2021-07-26 10:29:34.383110", "stderr": "useradd:用户“shen”已存在", "stderr_lines": ["useradd:用户“shen”已存在"], "stdout": "更改用户 shen 的密码 。\npasswd:所有的身份验证令牌已经成功更新。", "stdout_lines": ["更改用户 shen 的密码 。", "passwd:所有的身份验证令牌已经成功更新。"]}

PLAY RECAP *********************************************************************
192.168.100.147            : ok=1    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0 

fail模块也可用于强制任务失败。上面的场景也可以编写为两个任务:

[root@node1 ansible]# cat node/test.yml 
---
- name: create user
  hosts: 192.168.100.147
  tasks: 
    - name: test
      command: /opt/shen.sh
      register: long
      ignore_errors: yes 
    - name: fjajrajrkfjt
      fail: 
        msg: "宝,用户已经创建过了啊!!"    //指定报错后输出什么
      when: "'useradd'"
[root@node1 ansible]# 



[root@node1 ansible]# ansible-playbook node/test.yml 

PLAY [create user] *************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [test] ********************************************************************
changed: [192.168.100.147]

TASK [fjajrajrkfjt] ************************************************************
fatal: [192.168.100.147]: FAILED! => {"changed": false, "msg": "宝,用户已经创建过了啊!!"}

PLAY RECAP *********************************************************************
192.168.100.147            : ok=2    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0  

我们可以使用fail模块为任务提供明确的失败消息。此方法还支持延迟失败,允许在运行中间任务以完成或回滚其他更改。

8.指定何时任务报告“changed”结果

当任务对托管主机进行了更改时,会报告 changed 状态并通知处理程序。如果任务不需要进行更改,则会报告ok并且不通知处理程序。

changed_when关键字可用于控制任务在何时报告它已进行了更改。例如,下一示例中的shell模块将用于获取供后续任务使用的Kerberos凭据。它通常会在运行时始终报告changed。为抵制这种更改,应设置changed_when: false,以便它仅报告okfailed

- name: get Kerberos credentials as "admin"
  shell: echo "{{ krb_admin_pass }}" | kinit -f admin
  changed_when: false

以下示例使用shell模块,根据通过已注册变量收集的模块的输出来报告changed

[root@node1 ansible]# cat node/test.yml ---
- name: create user
  hosts: 192.168.100.147
  tasks: 
    - name: test
      shell: echo "runtime" | passwd --stdin shen
      register: long
      notify: 
        - print info
  handlers:
    - name: print info
      debug:
        msg: "宝,密码已经设置成功了!!" 
[root@node1 ansible]# 


[root@node1 ansible]# ansible-playbook node/test.yml 

PLAY [create user] *************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [test] ********************************************************************
changed: [192.168.100.147]

RUNNING HANDLER [print info] ***************************************************
ok: [192.168.100.147] => {
    "msg": "宝,密码已经设置成功了!!"
}

PLAY RECAP *********************************************************************
192.168.100.147            : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

9.ansible块和错误处理

playbook中,块是对任务进行逻辑分组的子句,可用于控制任务的执行方式。例如,任务块可以含有when关键字,以将某一条件应用到多个任务:

- name: block example
  hosts: 172.16.103.129
  tasks:
    - name: installing and configuring Yum versionlock plugin
      block:
      - name: package needed by yum
        yum:
          name: yum-plugin-versionlock
          state: present
      - name: lock version of tadata
        lineinfile:
          dest: /etc/yum/pluginconf.d/versionlock.list
          line: tzdata-2020j-1
          state: present
      when: ansible_distribution == "Redhat"

通过块,也可结合rescuealways语句来处理错误。如果块中的任何任务失败,则执行其rescue块中的任务来进行恢复。在block子句中的任务以及rescue子句中的任务(如果出现故障)运行之后,always子句中的任务运行。总结:

  • block:定义要运行的主要任务

  • rescue:定义要在block子句中定义的任务失败时运行的任务

  • always:定义始终都独立运行的任务,不论blockrescue子句中定义的任务是成功还是失败

    以下示例演示了如何在playbook中实施块。即使block子句中定义的任务失败,rescue和always子句中定义的任务也会执行。

tasks:
  - name: Upgrade DB
    block:    //如果我任务执行成功了 ,那么后面的任务就不执行,如果执行失败,就执行rescure里面的
      - name: upgrade the database
        shell:
          cmd: /usr/local/lib/upgrade-database
    rescue:
      - name: revert the database upgrade
        shell:
          cmd: /usr/local/lib/revert-database
    always:    //不管上面成功不成功。alway是一定会执行的
      - name: always restart the database
        service:
          name: mariadb
          state: restarted

block中的when条件也会应用到其rescue和always子句(若存在)。

修改文件并将其复制到主机

10.描述文件模块

Files模块库包含的模块允许用户完成与Linux文件管理相关的大多数任务,如创建、复制、编辑和修改文件的权限和其他属性。下表提供了常用文件管理模块的列表:

常用的文件模块

模块名称模块说明
blockinfile插入、更新或删除由可自定义标记线包围的多行文本块
copy将文件从本地或远程计算机复制到受管主机上的某个位置。 类似于file模块,copy模块还可以设置文件属性,包括SELinux上下文件。
fetch此模块的作用和copy模块类似,但以相反方式工作。此模块用于从远程计算机获取文件到控制节点, 并将它们存储在按主机名组织的文件树中。
file设置权限、所有权、SELinux上下文以及常规文件、符号链接、硬链接和目录的时间戳等属性。 此模块还可以创建或删除常规文件、符号链接、硬链接和目录。其他多个与文件相关的 模块支持与file模块相同的属性设置选项,包括copy模块。
lineinfile确保特定行位于某文件中,或使用反向引用正则表达式来替换现有行。 此模块主要在用户想要更改文件的某一行时使用。
stat检索文件的状态信息,类似于Linux中的stat命令。
synchronize围绕rsync命令的一个打包程序,可加快和简化常见任务。 synchronize模块无法提供对rsync命令的完整功能的访问权限,但确实最常见的调用更容易实施。 用户可能仍需通过run command模块直接调用rsync命令。

12.files模块的自动化示例

在受管主机上创建、复制、编辑和删除文件是用户可以使用Files模块库中的模块实施的常见任务。
以下示例显示了可以使用这些模块自动执行常见文件管理任务的方式。

13.确保受管主机上存在文件

使用file模块处理受管主机上的文件。其工作方式与touch命令类似,如果不存在则创建一个空文件,如果存在,则更新其修改时间。在本例中,除了处理文件之外,Ansible还确保将文件的所有者、组和权限设置为特定值。

- name: Touch a file and set permissions
  file:
    path: /path/to/file   //路径
    owner: user1
    group: group1   //组
    mode: 0640    //权限
    state: touch    //这里的意思是创建一个空文件。

14.修改文件属性

使用file模块还可以确保新的或现有的文件具有正确的权限和SELinux类型。

例如,以下文件保留了相对于用户主目录的默认SELinux上下文,这不是所需的上下文

[root@node1 ~]# ls -Z anaconda-ks.cfg    //我们查看受管主机root下的一个文件
system_u:object_r:admin_home_t:s0 anaconda-ks.cfg     //修改它的权限  
[root@node1 ~]# 


[root@node1 ~]# cat /etc/ansible/node/test.yml   //play写法
---
- name: create user
  hosts: 192.168.100.147
  tasks: 
    - name: test
      file: 
        path: /root/anaconda-ks.cfg
        setype: shen_niubi_shuaiqi_t    //改为我们想要的
[root@node1 ~]# 


[root@localhost ~]# ls -Z anaconda-ks.cfg    //修改成功
system_u:object_r:shen_niubi_shuaiqi_t:s0 anaconda-ks.cfg
[root@localhost ~]# 

15.使用SELINUX文件上下文更改具有持久性

设置文件上下文时,file模块的行为与chcon类似。通过运行restorecon,可能会意外地撤消使用该模块所做的更改。使用file设置上下文后,用户可以使用system模块集合中的sefcontext来更新SELinux策略,如semanage fcontext

- name: Copy a file to managed hosts   //这是我们常用的做法
  copy:
    src: file
    dest: /path/to/file

要从受管主机检索文件,请使用fetch模块。这可用于在将参考系统分发给其他受管主机之前从参考系统中检查诸如SSH公钥之类的文件。

[root@localhost ~]# ls    //受管主机上root下面有一个脚本, 我要把它弄到我控制机上
anaconda-ks.cfg  test.sh
[root@localhost ~]# 


[root@node1 ansible]# cat node/test.yml     //play写法
---
- name: create user
  hosts: 192.168.100.147
  tasks: 
    - name: test
      fetch: 
        src: /root/test.sh     //注意它和copy不一样,这里是受管主机的路径
        dest: /root/      //这里才是控制机的路径,他和copy是反的
[root@node1 ansible]# 


[root@node1 ansible]# ansible-playbook node/test.yml 

PLAY [create user] *************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [test] ********************************************************************
changed: [192.168.100.147]

PLAY RECAP *********************************************************************
192.168.100.147            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

[root@node1 ansible]# ls /root
192.168.100.147  scripts  test.sh    //可以看见受管主机文件已经到控制机上了
anaconda-ks.cfg  testdir
[root@node1 ansible]# 

要确保现有文件中存在特定的单行文本,请使用lineinfile模块:

- name: Add a line of text to a file   //代码格式如下,具体可以看前面发行的博客
  lineinfile:
    path: /path/to/file
    line: 'Add this line to the file'
    state: present

要将文本块添加到现有文件,请使用blockinfile模块:

[root@node1 ansible]# cat node/test.yml 
---
- name: create user
  hosts: 192.168.100.147
  tasks: 
    - name: test
      blockinfile: 
        path: /tmp/shen   //给受管主机tmp下面添加文本
        block: |
          shunzi chishi 
          hello shunzi
          helle shuaige
          hello SB
        state: present
        create: yes    //没有文件的,自动创建
[root@node1 ansible]# 

[root@node1 ansible]# ansible-playbook node/test.yml   //执行成功

PLAY [create user] *************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [test] ********************************************************************
changed: [192.168.100.147]

PLAY RECAP *********************************************************************
192.168.100.147            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[root@localhost ~]# cd /tmp
[root@localhost tmp]# ls
shen   //创建成功
systemd-private-2126c22bfcc7458eac8d84abfdcb844c-chronyd.service-Vd9cpx
systemd-private-2126c22bfcc7458eac8d84abfdcb844c-httpd.service-xjP1M8
[root@localhost tmp]# cat shen    //文本加入成功
# BEGIN ANSIBLE MANAGED BLOCK
shunzi chishi 
hello shunzi
helle shuaige
hello SB
# END ANSIBLE MANAGED BLOCK
[root@localhost tmp]#

注意:使用blockinfile模块时,注释块标记插入到块的开头和结尾,以确保幂等性

# BEGIN ANSIBLE MANAGED BLOCK
shunzi chishi 
hello shunzi
helle shuaige
hello SB
# END ANSIBLE MANAGED BLOCK

用户可以使用该模块的marker参数,帮助确保将正确的注释字符或文本用于相关文件。

16.从守寡主机中删除文件

从受管主机中删除文件的基本示例是使用file模块和state: absent参数。state参数对于许多模块是可选的。一些模块也支持其他选项。

[root@node1 ansible]# cat node/test.yml    //删除上面创建的shen
---
- name: create user
  hosts: 192.168.100.147
  tasks: 
    - name: test
      file: 
        dest: /tmp/shen
        state: absent
[root@node1 ansible]# 


[root@node1 ansible]# ansible-playbook node/test.yml    //执行成功

PLAY [create user] *************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [test] ********************************************************************
changed: [192.168.100.147]

PLAY RECAP *********************************************************************
192.168.100.147            : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0


[root@localhost tmp]# ls    //查看此时已经没有,已经被删除
systemd-private-2126c22bfcc7458eac8d84abfdcb844c-chronyd.service-Vd9cpx
systemd-private-2126c22bfcc7458eac8d84abfdcb844c-httpd.service-xjP1M8
[root@localhost tmp]

17.检索受管主机上的文件状态

stat模块检索文件的事实,类似于Linux中的stat命令。参数提供检索文件属性、确定文件检验和等功能。

stat模块返回一个包含文件状态数据的值的散列字典,允许用户使用单独的变量引用各条信息。

以下示例注册stat模块的结果,然后显示它检查的文件的MD5检验和。

有关stat模块返回的值的信息由ansible-doc记录,或者可以注册一个变量并显示其内容以查看可用内容:

[root@node1 ansible]# cat node/test.yml 
---
- name: create user
  hosts: 192.168.100.147
  tasks: 
    - name: test
      stat: 
        path: /root/test.sh
      register: long
    - debug: 
        var: long
[root@node1 ansible]# 


[root@node1 ansible]# ansible-playbook node/test.yml 

PLAY [create user] *************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [test] ********************************************************************
ok: [192.168.100.147]

TASK [debug] *******************************************************************
ok: [192.168.100.147] => {
    "long": {
        "changed": false,
        "failed": false,
        "stat": {
            "atime": 1627311982.0563967,
            "attr_flags": "",
            "attributes": [],
            "block_size": 4096,
            "blocks": 0,
            "charset": "binary",
            "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709",
            "ctime": 1627311840.0285206,
此处内容省略。。。。。。
 
        }
    }
}

PLAY RECAP *********************************************************************
192.168.100.147            : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

18.同步控制节点和受管主机之间的文件

synchronize模块是一个围绕rsync工具的打包程序,它简化了playbook中的常见文件管理任务。rsync工具必须同时安装在本机和远程主机上。默认情况下,在使用synchronize模块时,“本地主机”是同步任务所源自的主机(通常是控制节点),而“目标主机”是synchronize连接到的主机。

以下示例将位于Ansible工作目录中的文件同步到受管主机

[root@node1 node]# ls    //我想把控制机中这个httpd同步到受管主机中
httpd  test.yml
[root@node1 node]# 


[root@node1 ansible]# cat node/test.yml 
---
- name: create user
  hosts: 192.168.100.147
  tasks: 
    - name: test
      yum:
        name: rsync     //必须下载rsync
        state: present
    - name: 
      synchronize:   //用这个模块
        src: httpd     //原地址下的httpd
        dest: /opt/httpd    //同步到受管主机opt下面
[root@node1 ansible]# 

[root@node1 ansible]# ansible-playbook node/test.yml    //执行成功

PLAY [create user] *************************************************************

TASK [Gathering Facts] *********************************************************
ok: [192.168.100.147]

TASK [test] ********************************************************************
changed: [192.168.100.147]

TASK [synchronize] *************************************************************
changed: [192.168.100.147]

PLAY RECAP *********************************************************************
192.168.100.147            : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

[root@localhost opt]# ls   //这边可以看到已经同步过来了
httpd  shen.sh
[root@localhost opt]# 

有很多种方法可以使用synchronize模块及其许多参数,包括同步目录。运行ansible-doc synchronize命令查看其他参数和playbook示例。

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-07-27 16:38:53  更:2021-07-27 16:39:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/27 11:16:25-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计