zoukankan      html  css  js  c++  java
  • Ansible批量管理软件的使用

    Ansible批量管理软件的使用

    一、ansible介绍

    1.1.1 什么是ansible

    ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
      ansible是基于 paramiko 开发的,并且基于模块化工作,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架。ansible不需要在远程主机上安装client/agents,因为它们是基于ssh来和远
    程主机通讯的。ansible目前已经已经被红帽官方收购,是自动化运维工具中大家认可度最高的,并且上手容易,学习简单。是每位运维工程师必须掌握的技能之一。

    1.1.2 ansible的特点

    1. 部署简单,只需在主控端部署Ansible环境,被控端无需做任何操作:
    2. 默认使用SSH协议对设备进行管理;有大量常规运维操作模块,可实现日常绝大部分操作;
    3. 配置简单、功能强大、扩展性强;
    4. 支持API及自定义模块,可通过Python轻松扩展;
    5. 通过Playbooks来定制强大的配置、状态管理;
    6. 轻量级,无需在客户端安装agent,更新时,只需在操作机上进行一次更新即可;
    7. 提供一个功能强大、操作性强的Web管理界面和REST API接口——AWX平台。

    1.1.3 为什么要用ansible

    1. 提高工作效率.
    2. 提高公司资源利用力。
    3. 节省公司成本。
      官方:http://docs.ansible.com

    二、Ansible环境实战

    2.1.1 安装ansible

    1. ansible管理节点安装
    [root@m01 ~]# yum install epel-release -y
    [root@m01 ~]# yum install ansible  libselinux-python -y
    [root@m01 ~]# rpm -qa ansible
    ansible-2.9.7-1.el7.noarch
    
    1. ansible 远程控制节点安装
    [root@backup ~]# yum install libselinux-python -y
    [root@nfs01 ~]# yum install libselinux-python -y
    [root@web02 ~]# yum install libselinux-python -y
    

    2.1.3 配置ansible主机配置文件

    1. 主机配置文件/etc/ansible/hosts
    [root@m01 ~]# cp /etc/ansible/hosts{,.bak}
    [root@m01 ~]# ll  /etc/ansible/hosts{,.bak}
    -rw-r--r-- 1 root root 1016 Apr 19 05:24 /etc/ansible/hosts
    -rw-r--r-- 1 root root 1016 May  3 12:57 /etc/ansible/hosts.bak
    [root@m01 ~]# vim /etc/ansible/hosts 
    #配置如下:
    [root@m01 ~]# tail -8 /etc/ansible/hosts
    [oldboy]
    172.16.1.31
    172.16.1.41
    
    [oldgirl]
    172.16.1.31
    172.16.1.41
    172.16.1.51
    #####
    #/etc/ansible/hosts主机资产清单文件,用于定义被管理主机的认证信息, 
    例如ssh登录用户名、密码以及key相关信息。如何配置Inventory文件
    1.主机支持主机名通配以及正则表达式,例如web[1:3].oldboy.com代表三台主机
    2.主机支持基于非标准的ssh端口,例如web1.oldboyedu.com:6666
    3.主机支持指定变量,可对个别主机的特殊配置,如登陆用户密码
    4.主机组支持指定变量[group_name:vars],同时支持嵌套组[game:children]
    
    1. 配置/etc/ansible/ansible.cfg
    [root@m01 ~]# ll /etc/ansible/ansible.cfg{,.bak}
    -rw-r--r-- 1 root root 20013 May  3 14:23 /etc/ansible/ansible.cfg
    -rw-r--r-- 1 root root 20013 May  3 14:39 /etc/ansible/ansible.cfg.bak
    [root@m01 ~]# vim /etc/ansible/ansible.cfg
    修改ansible.cfg 374行:
    ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no
    # 在此行后面加入-o StrictHostKeyChecking=no
    
    1. 实战命令
    报错:
    [root@m01 ~]# ansible oldboy -m command -a "ifconfig eth1"
    The authenticity of host '172.16.1.31 (172.16.1.31)' can't be established.
    ECDSA key fingerprint is SHA256:bbt9sjPOENs3zK9cw7YmIo0ABuFkZnTxXbOaIdpSOo0.
    ECDSA key fingerprint is MD5:e5:3b:15:2e:6c:82:4b:b1:f8:45:dc:80:72:de:11:47.
    Are you sure you want to continue connecting (yes/no)? The authenticity of host '172.16.1.41 (172.16.1.41)' can't be established.
    ECDSA key fingerprint is SHA256:bbt9sjPOENs3zK9cw7YmIo0ABuFkZnTxXbOaIdpSOo0.
    ECDSA key fingerprint is MD5:e5:3b:15:2e:6c:82:4b:b1:f8:45:dc:80:72:de:11:47.
    Are you sure you want to continue connecting (yes/no)? yes
    172.16.1.31 | UNREACHABLE! => {
        "changed": false, 
        "msg": "Failed to connect to the host via ssh: Warning: Permanently added '172.16.1.31' (ECDSA) to the list of known hosts.
    Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", 
        "unreachable": true
    }
    
    172.16.1.41 | UNREACHABLE! => {
        "changed": false, 
        "msg": "Failed to connect to the host via ssh: Host key verification failed.", 
        "unreachable": true
    }
    

    解决方法:

    [oldboy]
    172.16.1.31 ansible_ssh_user=root ansible_ssh_pass=123456
    172.16.1.41 ansible_ssh_user=root ansible_ssh_pass=123456
    #模块后面加上认证信息,让后手动ssh登录到对应IP主机,也可以基于秘钥解决此问题(推荐方案)
    
    [root@m01 ~]# ansible oldboy -m command -a "ifconfig eth1"
    172.16.1.31 | CHANGED | rc=0 >>
    eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.16.1.31  netmask 255.255.0.0  broadcast 172.16.255.255
            inet6 fe80::20c:29ff:fea2:2c6d  prefixlen 64  scopeid 0x20<link>
            ether 00:0c:29:a2:2c:6d  txqueuelen 1000  (Ethernet)
            RX packets 492  bytes 364464 (355.9 KiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 345  bytes 45470 (44.4 KiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    172.16.1.41 | CHANGED | rc=0 >>
    eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
            inet 172.16.1.41  netmask 255.255.0.0  broadcast 172.16.255.255
            inet6 fe80::20c:29ff:fe6c:1f2d  prefixlen 64  scopeid 0x20<link>
            ether 00:0c:29:6c:1f:2d  txqueuelen 1000  (Ethernet)
            RX packets 209  bytes 107503 (104.9 KiB)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 171  bytes 30025 (29.3 KiB)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
    
    1. 秘钥分发
    [root@m01 ~]# sh /server/scripts/rsa_pub.sh 
    ========172.16.1.31=========
    /bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
    /bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
    /bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
    
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh -o 'StrictHostKeyChecking=no' 'root@172.16.1.31'"
    and check to make sure that only the key(s) you wanted were added.
    
    its sopy successful                                        [  OK  ]
    ========172.16.1.41=========
    /bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
    /bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
    /bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
    
    Number of key(s) added: 1
    
    Now try logging into the machine, with:   "ssh -o 'StrictHostKeyChecking=no' 'root@172.16.1.41'"
    and check to make sure that only the key(s) you wanted were added.
    
    its sopy successful                                        [  OK  ]
    
    1. 秘钥脚本
    [root@m01 ~]# vim /server/scripts/rsa_pub.sh 
    #!/bin/bash
    #auth chenhj 2020-2-15
    . /etc/init.d/functions
    #ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa
    for ip in {31,41}
    do
            echo "========172.16.1.$ip========="
            sshpass -p123456 ssh-copy-id -i ~/.ssh/id_rsa.pub "'ssh -o StrictHostKeyChecking=no' 'root@172.16.1.$ip'"
            action  "its sopy successful "        /bin/true
    done
    
    [root@m01 ~]# ansible oldboy -m command -a "ifconfig eth1"
    172.16.1.31 | UNREACHABLE! => {
        "changed": false, 
        "msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", 
        "unreachable": true
    }
    172.16.1.41 | UNREACHABLE! => {
        "changed": false, 
        "msg": "Failed to connect to the host via ssh: Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", 
        "unreachable": true
    }
    
    1. 实战
    [root@m01 ~]# ansible oldboy -m command -a "free -m"
    172.16.1.41 | CHANGED | rc=0 >>
                  total        used        free      shared  buff/cache   available
    Mem:           1980         110        1603           9         266        1716
    Swap:          1023           0        1023
    172.16.1.31 | CHANGED | rc=0 >>
                  total        used        free      shared  buff/cache   available
    Mem:           1980         117        1595           9         268        1710
    Swap:          1023           0        1023
    

    三、ansible常用模块

    3.1.1 查看ansible模块

    [root@m01 ~]# ansible-doc -l
    fortios_router_community_list                                 Configure community lists in Fortinet's FortiOS and FortiGate     
    azure_rm_devtestlab_info                                      Get Azure DevTest Lab facts                                       
    ecs_taskdefinition                                            register a task definition in ecs                                 
    avi_alertscriptconfig                                         Module for setup of AlertScriptConfig Avi RESTful Object          
    tower_receive                                                 Receive assets from Ansible Tower                                 
    netapp_e_iscsi_target                                         NetApp E-Series manage iSCSI target configuration                 
    azure_rm_acs                                                  Manage an Azure Container Service(ACS) instance                   
    fortios_log_syslogd2_filter                                   Filters for remote system server in Fortinet's FortiOS and FortiGa...
    junos_rpc                                                     Runs an arbitrary RPC ove
    .....。
    

    3.1.2 ansible常用用参数

    -m MODULE_NAME, 模块名字,默认command
    -a MODULE_ARGS, 模块参数
    -f FORKS	    并发进程数,默认5个。
    -i INVENTORY(default=/etc/ansible/hosts)指定主机列表文件
    

    指定hosts主机文件

    [root@m01 /etc/ansible]# ansible -i /etc/ansible/webhosts oldgirl -m command -a "free -m"
    172.16.1.41 | CHANGED | rc=0 >>
                  total        used        free      shared  buff/cache   available
    Mem:           1980         110        1601           9         268        1716
    Swap:          1023           0        1023
    172.16.1.31 | CHANGED | rc=0 >>
                  total        used        free      shared  buff/cache   available
    Mem:           1980         118        1587           9         273        1708
    Swap:          1023           0        1023
    172.16.1.51 | UNREACHABLE! => {
        "changed": false, 
        "msg": "Failed to connect to the host via ssh: ssh: connect to host 172.16.1.51 port 22: Connection timed out", 
        "unreachable": true
    }
    

    3.1.3 command(命令)模块

    1. 查看command 模块参数
    [root@m01 ~]# ansible-doc -s command
    - name: Execute commands on targets
      command:
          argv:                  # Passes the command as a list rather than a string. Use `argv' to avoid quoting values that would
                                   otherwise be interpreted incorrectly (for example "user name"). Only
                                   the string or the list form can be provided, not both.  One or the
                                   other must be provided.
          chdir:                 # Change into this directory before running the command.
          cmd:                   # The command to run.
          creates:               # A filename or (since 2.0) glob pattern. If it already exists, this step *won't* be run.
          free_form:             # The command module takes a free form command to run. There is no actual parameter named 'free form'.
          removes:               # A filename or (since 2.0) glob pattern. If it already exists, this step *will* be run.
          stdin:                 # Set the stdin of the command directly to the specified value.
          stdin_add_newline:     # If set to `yes', append a newline to stdin data.
          strip_empty_ends:      # Strip empty lines from the end of stdout/stderr in result.
          warn:                  # Enable or disable task warnings.
    
    1. command 的使用
    [root@m01 ~]# ansible oldboy -m command -a "free -m"
    172.16.1.41 | CHANGED | rc=0 >>
                  total        used        free      shared  buff/cache   available
    Mem:           1980         110        1602           9         267        1716
    Swap:          1023           0        1023
    172.16.1.31 | CHANGED | rc=0 >>
                  total        used        free      shared  buff/cache   available
    Mem:           1980         119        1591           9         269        1707
    Swap:          1023           0        1023
    [root@m01 ~]# ansible oldboy -m command -a "cat /etc/hosts"
    172.16.1.41 | CHANGED | rc=0 >>
    127.0.0.1    localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1          localhost localhost.localdomain localhost6 localhost6.localdomain6
    172.16.1.5 lb01
    172.16.1.6 lb02
    172.16.1.7 web01
    172.16.1.8 web02
    172.16.1.9 web03
    172.16.1.31 nfs01
    172.16.1.41 backup
    172.16.1.51 db01 db01.etiantian.org
    172.16.1.61 m01
    172.16.1.31 | CHANGED | rc=0 >>
    127.0.0.1    localhost localhost.localdomain localhost4 localhost4.localdomain4
    ::1          localhost localhost.localdomain localhost6 localhost6.localdomain6
    172.16.1.5 lb01
    172.16.1.6 lb02
    172.16.1.7 web01
    172.16.1.8 web02
    172.16.1.9 web03
    172.16.1.31 nfs01
    172.16.1.41 backup
    172.16.1.51 db01 db01.etiantian.org
    172.16.1.61 m01
    #有些符号信息无法识别:  <", ">", "|", ";" and "&"
    
    1. 常用参数
    参数:chdir=/tmp配置相当于cd /tmp
    [root@m01 ~]# ansible oldboy  -m command -a "pwd chdir=/etc"
    ansible oldboy  -m shell -a "cd /etc/;pwd"
     
    参数:creates=/etc  相当于条件测试  [ -e /etc ]||pwd 和下面removes相反
    [root@m01 ~]# ansible oldboy  -m command -a "pwd creates=/etc"
    
    参数:removes=/root 相当于条件测试 [ -e /root ]&&ls /root
    ansible oldboy  -m command -a "ls /root removes=/root"
    ansible oldboy  -m shell -a "[ -d /etc ]||pwd"
    [root@m01 ~]# ansible oldboy  -m command -a "cat /etc/hosts removes=/etc/hosts"
    
    参数:warn=False 忽略警告
    [root@m01 ~]# ansible oldboy  -m command -a "chmod 000 /etc/hosts warn=False"
    
    1. chdir 参数使用
    [root@m01 ~]# ansible -f 10 oldboy -m command -a "pwd chdir=/etc"
    172.16.1.31 | CHANGED | rc=0 >>
    /etc
    172.16.1.41 | CHANGED | rc=0 >>
    /etc
    [root@m01 ~]# ansible -f 10 oldboy -m command -a "chdir=/etc  pwd"
    172.16.1.31 | CHANGED | rc=0 >>
    /etc
    172.16.1.41 | CHANGED | rc=0 >>
    /etc
    #相当于cd命令
    
    1. creates 参数使用 判断参数,如果那么
    [root@m01 ~]# ansible -f 10 oldboy -m command -a "creates=/root pwd"
    172.16.1.41 | SUCCESS | rc=0 >>
    skipped, since /root exists
    172.16.1.31 | SUCCESS | rc=0 >>
    skipped, since /root exists
    #如果/root存在,就不执行pwd命令
    [root@m01 ~]# ansible -f 10 oldboy -m command -a "creates=/ccc pwd"
    172.16.1.41 | CHANGED | rc=0 >>
    /root
    172.16.1.31 | CHANGED | rc=0 >>
    /root
    #如果/ccc 不存在。就执行pwd命令
    
    1. warn 参数 忽略警告信息
    [root@m01 ~]# ansible -f 10 oldboy -m command -a "chmod 000 /etc"
    [WARNING]: Consider using the file module with mode rather than running 'chmod'.  If you need to use command because file is
    insufficient you can add 'warn: false' to this command task or set 'command_warnings=False' in ansible.cfg to get rid of this
    message.
    172.16.1.41 | CHANGED | rc=0 >>
    
    172.16.1.31 | CHANGED | rc=0 >>
    [root@m01 ~]# ansible -f 10 oldboy -m command -a "warn=false chmod 000 /etc"
    172.16.1.31 | CHANGED | rc=0 >>
    
    172.16.1.41 | CHANGED | rc=0 >>
    #注意记得把权限改回来
    [root@m01 ~]# ansible -f 10 oldboy -m command -a "warn=false chmod 755 /etc"
    172.16.1.41 | CHANGED | rc=0 >>
    
    172.16.1.31 | CHANGED | rc=0 >>
    
    
    1. removes 参数 判断参数与creates刚好相反
    [root@m01 ~]# ansible  172.16.1.31 -m command -a "ls -l removes=/root"
    172.16.1.31 | CHANGED | rc=0 >>
    total 4
    -rw-------. 1 root root 1525 Mar 26 22:43 anaconda-ks.cfg
    [root@m01 ~]# ansible  172.16.1.31 -m command -a "ls -l removes=/ss
    > 
    > "
    172.16.1.31 | SUCCESS | rc=0 >>
    skipped, since /ss does not exist
    [root@m01 ~]# ansible  172.16.1.31 -m command -a "ls -l removes=/ss"
    172.16.1.31 | SUCCESS | rc=0 >>
    skipped, since /ss does not exist
    

    3.1.4 shell 模块

    1. shell 模块参数 在远端执行命令
    [root@m01 ~]# ansible-doc -s shell
    - name: Execute shell commands on targets
      shell:
          chdir:                 # Change into this directory before running the command.
          cmd:                   # The command to run followed by optional arguments.
          creates:               # A filename, when it already exists, this step will *not* be run.
          executable:            # Change the shell used to execute the command. This expects an absolute path to the executable.
          free_form:             # The shell module takes a free form command to run, as a string. There is no actual parameter named
                                   'free form'. See the examples on how to use this module.
          removes:               # A filename, when it does not exist, this step will *not* be run.
          stdin:                 # Set the stdin of the command directly to the specified value.
          stdin_add_newline:     # Whether to append a newline to stdin data.
          warn:                  # Whether to enable task warnings.
    
    1. shell 模块实战
    [root@m01 ~]# ansible oldboy -m shell -a "echo oldboy >/tmp/oldboy.txt"
    172.16.1.41 | CHANGED | rc=0 >>
    
    172.16.1.31 | CHANGED | rc=0 >>
    
    [root@m01 ~]# ansible oldboy -m shell -a "cat /tmp/oldboy.txt"
    172.16.1.41 | CHANGED | rc=0 >>
    oldboy
    172.16.1.31 | CHANGED | rc=0 >>
    oldboy
    
    1. 在远程节点执行脚本
    [root@m01 ~]# ansible oldboy -m shell -a "sh /server/scripts/back.sh"
    172.16.1.31 | FAILED | rc=127 >>
    sh: /server/scripts/back.sh: No such file or directorynon-zero return code
    172.16.1.41 | CHANGED | rc=0 >>
    #31上没有脚本所以没有执行成功
    

    3.1.5 copy模块使用 copy 文件远程节点主机

    1. copy 模块的参数
    [root@m01 ~]# ansible-doc -s copy
    - name: Copy files to remote locations
      copy:
          attributes:            # The attributes the resulting file or directory should have. To get supported flags look at the man
                                   page for `chattr' on the target system. This string should contain the
                                   attributes in the same order as the one displayed by `lsattr'. The `='
                                   operator is assumed as default, otherwise `+' or `-' operators need to
                                   be included in the string.
          backup:                # Create a backup file including the timestamp information so you can get the original file back if you
                                   somehow clobbered it incorrectly.
          checksum:              # SHA1 checksum of the file being transferred. Used to validate that the copy of the file was
                                   successful. If this is not provided, ansible will use the local
                                   calculated checksum of the src file.
          content:               # When used instead of `src', sets the contents of a file directly to the specified value. Works only
                                   when `dest' is a file. Creates the file if it does not exist. For
                                   advanced formatting or if `content' contains a variable, use the
                                   [template] module.
          decrypt:               # This option controls the autodecryption of source files using vault.
          dest:                  # (required) Remote absolute path where the file should be copied to. If `src' is a directory, this
                                   must be a directory too. If `dest' is a non-existent path and if
                                   either `dest' ends with "/" or `src' is a directory, `dest' is
                                   created. If `dest' is a relative path, the starting directory is
                                   determined by the remote host. If `src' and `dest' are files, the
                                   parent directory of `dest' is not created and the task fails if it
                                   does not already exist.
          directory_mode:        # When doing a recursive copy set the mode for the directories. If this is not set we will use the
                                   system defaults. The mode is only set on directories which are newly
                                   created, and will not affect those that already existed.
          follow:                # This flag indicates that filesystem links in the destination, if they exist, should be followed.
          force:                 # Influence whether the remote file must always be replaced. If `yes', the remote file will be replaced
                                   when contents are different than the source. If `no', the file will
                                   only be transferred if the destination does not exist. Alias `thirsty'
                                   has been deprecated and will be removed in 2.13.
          group:                 # Name of the group that should own the file/directory, as would be fed to `chown'.
          local_follow:          # This flag indicates that filesystem links in the source tree, if they exist, should be followed.
          mode:                  # The permissions of the destination file or directory. For those used to `/usr/bin/chmod' remember
                                   that modes are actually octal numbers. You must either add a leading
                                   zero so that Ansible's YAML parser knows it is an octal number (like
                                   `0644' or `01777')or quote it (like `'644'' or `'1777'') so Ansible
                                   receives a string and can do its own conversion from string into
                                   number. Giving Ansible a number without following one of these rules
                                   will end up with a decimal number which will have unexpected results.
                                   As of Ansible 1.8, the mode may be specified as a symbolic mode (for
                                   example, `u+rwx' or `u=rw,g=r,o=r'). As of Ansible 2.3, the mode may
                                   also be the special string `preserve'. `preserve' means that the file
                                   will be given the same permissions as the source file.
          owner:                 # Name of the user that should own the file/directory, as would be fed to `chown'.
          remote_src:            # Influence whether `src' needs to be transferred or already is present remotely. If `no', it will
                                   search for `src' at originating/master machine. If `yes' it will go to
                                   the remote/target machine for the `src'. `remote_src' supports
                                   recursive copying as of version 2.8. `remote_src' only works with
                                   `mode=preserve' as of version 2.6.
          selevel:               # The level part of the SELinux file context. This is the MLS/MCS attribute, sometimes known as the
                                   `range'. When set to `_default', it will use the `level' portion of
                                   the policy if available.
          serole:                # The role part of the SELinux file context. When set to `_default', it will use the `role' portion of
                                   the policy if available.
          setype:                # The type part of the SELinux file context. When set to `_default', it will use the `type' portion of
                                   the policy if available.
          seuser:                # The user part of the SELinux file context. By default it uses the `system' policy, where applicable.
                                   When set to `_default', it will use the `user' portion of the policy
                                   if available.
          src:                   # Local path to a file to copy to the remote server. This can be absolute or relative. If path is a
                                   directory, it is copied recursively. In this case, if path ends with
                                   "/", only inside contents of that directory are copied to destination.
                                   Otherwise, if it does not end with "/", the directory itself with all
                                   contents is copied. This behavior is similar to the `rsync' command
                                   line tool.
          unsafe_writes:         # Influence when to use atomic operation to prevent data corruption or inconsistent reads from the
                                   target file. By default this module uses atomic operations to prevent
                                   data corruption or inconsistent reads from the target files, but
                                   sometimes systems are configured or just broken in ways that prevent
                                   this. One example is docker mounted files, which cannot be updated
                                   atomically from inside the container and can only be written in an
                                   unsafe manner. This option allows Ansible to fall back to unsafe
                                   methods of updating files when atomic operations fail (however, it
                                   doesn't force Ansible to perform unsafe writes). IMPORTANT! Unsafe
                                   writes are subject to race conditions and can lead to data corruption.
          validate:              # The validation command to run before copying into place. The path to the file to validate is passed
                                   in via '%s' which must be present as in the examples below. The
                                   command is passed securely so shell features like expansion and pipes
                                   will not work.
    
    1. 拷贝实战
    [root@m01 ~]# echo 'www.etiantian.org' >/data/www.txt
    [root@m01 ~]# ansible oldboy -m copy -a "src=/data/www.txt dest=/tmp"
    172.16.1.41 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "checksum": "6924137e624d26c6c12a19b9ef00f660f2f257ea", 
        "dest": "/tmp/www.txt", 
        "gid": 0, 
        "group": "root", 
        "md5sum": "15b54681ad5be5c9bc15bf7e70568b8c", 
        "mode": "0644", 
        "owner": "root", 
        "size": 18, 
        "src": "/root/.ansible/tmp/ansible-tmp-1588562286.01-4549-198862464258227/source", 
        "state": "file", 
        "uid": 0
    }
    172.16.1.31 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "checksum": "6924137e624d26c6c12a19b9ef00f660f2f257ea", 
        "dest": "/tmp/www.txt", 
        "gid": 0, 
        "group": "root", 
        "md5sum": "15b54681ad5be5c9bc15bf7e70568b8c", 
        "mode": "0644", 
        "owner": "root", 
        "size": 18, 
        "src": "/root/.ansible/tmp/ansible-tmp-1588562286.01-4547-162660185723539/source", 
        "state": "file", 
        "uid": 0
    }
    [root@m01 ~]# ansible oldboy -m shell -a "cat /tmp/www.txt"
    172.16.1.41 | CHANGED | rc=0 >>
    www.etiantian.org
    172.16.1.31 | CHANGED | rc=0 >>
    www.etiantian.org
    
    1. mode 赋予执行权限
    [root@m01 ~]# ansible oldboy -m shell -a "sh /server/scripts/echo.sh mode +x"
    172.16.1.41 | CHANGED | rc=0 >>
    
    172.16.1.31 | CHANGED | rc=0 >>
    
    [root@m01 ~]# ansible oldboy -m shell -a "cat /tmp/ce.txt"
    172.16.1.41 | CHANGED | rc=0 >>
    linuc ce
    172.16.1.31 | CHANGED | rc=0 >>
    linuc ce
    
    1. backup 拷贝文件需要备份,默认是no可以改成yes
    [root@m01 ~]# ansible oldboy -m copy -a "src=/etc/hosts dest=/etc/hosts backup=yes"
    172.16.1.41 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "backup_file": "/etc/hosts.7129.2020-05-04@09:00:37~", 
        "changed": true, 
        "checksum": "770fcea944a5bef27d92a24368c37c17b6cc5e69", 
        "dest": "/etc/hosts", 
        "gid": 0, 
        "group": "root", 
        "md5sum": "04610d311aea4d4fb5ae36a8ad978044", 
        "mode": "0644", 
        "owner": "root", 
        "size": 351, 
        "src": "/root/.ansible/tmp/ansible-tmp-1588563919.63-4788-3447571058700/source", 
        "state": "file", 
        "uid": 0
    }
    172.16.1.31 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "backup_file": "/etc/hosts.7842.2020-05-04@11:45:20~", 
        "changed": true, 
        "checksum": "770fcea944a5bef27d92a24368c37c17b6cc5e69", 
        "dest": "/etc/hosts", 
        "gid": 0, 
        "group": "root", 
        "md5sum": "04610d311aea4d4fb5ae36a8ad978044", 
        "mode": "0644", 
        "owner": "root", 
        "size": 351, 
        "src": "/root/.ansible/tmp/ansible-tmp-1588563919.62-4787-190909494933436/source", 
        "state": "file", 
        "uid": 0
    }
    [root@m01 ~]# ansible oldboy -m shell -a "ls -l /etc/hosts*"
    172.16.1.31 | CHANGED | rc=0 >>
    -rw-r--r--  1 root root 351 May  4 11:45 /etc/hosts
    -rw-r--r--  1 root root 332 May  1 04:32 /etc/hosts.7842.2020-05-04@11:45:20~
    -rw-r--r--. 1 root root 370 Jun  7  2013 /etc/hosts.allow
    -rw-r--r--. 1 root root 460 Jun  7  2013 /etc/hosts.deny
    172.16.1.41 | CHANGED | rc=0 >>
    -rw-r--r--  1 root root 351 May  4 09:00 /etc/hosts
    -rw-r--r--  1 root root 332 Apr 28 04:57 /etc/hosts.7129.2020-05-04@09:00:37~
    -rw-r--r--. 1 root root 370 Jun  7  2013 /etc/hosts.allow
    -rw-r--r--. 1 root root 460 Jun  7  2013 /etc/hosts.deny
    
    1. owner group 拷贝文件时更改用户和组
    [root@m01 ~]# ansible oldboy -m copy -a "src=/etc/hosts dest=/tmp/ owner=oldboy group=oldboy mode=700"
    172.16.1.41 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "checksum": "770fcea944a5bef27d92a24368c37c17b6cc5e69", 
        "dest": "/tmp/hosts", 
        "gid": 1000, 
        "group": "oldboy", 
        "md5sum": "04610d311aea4d4fb5ae36a8ad978044", 
        "mode": "0700", 
        "owner": "oldboy", 
        "size": 351, 
        "src": "/root/.ansible/tmp/ansible-tmp-1588564186.21-5008-11762490679403/source", 
        "state": "file", 
        "uid": 1000
    }
    172.16.1.31 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "checksum": "770fcea944a5bef27d92a24368c37c17b6cc5e69", 
        "dest": "/tmp/hosts", 
        "gid": 1000, 
        "group": "oldboy", 
        "md5sum": "04610d311aea4d4fb5ae36a8ad978044", 
        "mode": "0700", 
        "owner": "oldboy", 
        "size": 351, 
        "src": "/root/.ansible/tmp/ansible-tmp-1588564186.2-5006-89163945699600/source", 
        "state": "file", 
        "uid": 1000
    }
    [root@m01 ~]# ansible oldboy -m shell -a "ls -l /tmp/hosts"
    172.16.1.31 | CHANGED | rc=0 >>
    -rwx------ 1 oldboy oldboy 351 May  4 11:49 /tmp/hosts
    172.16.1.41 | CHANGED | rc=0 >>
    -rwx------ 1 oldboy oldboy 351 May  4 09:05 /tmp/hosts
    

    3.1.6 script 模块 在远程节点执行本地管理节点shell脚本

    1. script 参数
    [root@m01 ~]# ansible-doc -s script
    - name: Runs a local script on a remote node after transferring it
      script:
          chdir:                 # Change into this directory on the remote node before running the script.
          cmd:                   # Path to the local script to run followed by optional arguments.
          creates:               # A filename on the remote node, when it already exists, this step will *not* be run.
          decrypt:               # This option controls the autodecryption of source files using vault.
          executable:            # Name or path of a executable to invoke the script with.
          free_form:             # Path to the local script file followed by optional arguments.
          removes:               # A filename on the remote node, when it does not exist, this step will *not* be run.
    
    1. 实战
    [root@m01 ~]# ansible oldboy -m script -a "/server/scripts/www.sh"
    172.16.1.31 | CHANGED => {
        "changed": true, 
        "rc": 0, 
        "stderr": "Shared connection to 172.16.1.31 closed.
    ", 
        "stderr_lines": [
            "Shared connection to 172.16.1.31 closed."
        ], 
        "stdout": "", 
        "stdout_lines": []
    }
    172.16.1.41 | CHANGED => {
        "changed": true, 
        "rc": 0, 
        "stderr": "Shared connection to 172.16.1.41 closed.
    ", 
        "stderr_lines": [
            "Shared connection to 172.16.1.41 closed."
        ], 
        "stdout": "", 
        "stdout_lines": []
    }
    [root@m01 ~]# ansible oldboy -m shell -a "cat /tmp/linux.txt"
    172.16.1.41 | CHANGED | rc=0 >>
    www.sh
    172.16.1.31 | CHANGED | rc=0 >>
    www.sh
    

    3.1.7 fiel 模块 设置文件属性(可以穿件文件和目录)此模块相当鸡肋。

    1. file 模块参数
    [root@m01 ~]# ansible-doc -s file
    - name: Manage files and file properties
      file:
          access_time:           # This parameter indicates the time the file's access time should be set to. Should be `preserve' when
                                   no modification is required, `YYYYMMDDHHMM.SS' when using default time
                                   format, or `now'. Default is `None' meaning that `preserve' is the
                                   default for `state=[file,directory,link,hard]' and `now' is default
                                   for `state=touch'.
          access_time_format:    # When used with `access_time', indicates the time format that must be used. Based on default Python
                                   format (see time.strftime doc).
          attributes:            # The attributes the resulting file or directory should have. To get supported flags look at the man
                                   page for `chattr' on the target system. This string should contain the
                                   attributes in the same order as the one displayed by `lsattr'. The `='
                                   operator is assumed as default, otherwise `+' or `-' operators need to
                                   be included in the string.
          follow:                # This flag indicates that filesystem links, if they exist, should be followed. Previous to Ansible
                                   2.5, this was `no' by default.
          force:                 # Force the creation of the symlinks in two cases: the source file does not exist (but will appear
                                   later); the destination exists and is a file (so, we need to unlink
                                   the `path' file and create symlink to the `src' file in place of it).
          group:                 # Name of the group that should own the file/directory, as would be fed to `chown'.
          mode:                  # The permissions the resulting file or directory should have. For those used to `/usr/bin/chmod'
                                   remember that modes are actually octal numbers. You must either add a
                                   leading zero so that Ansible's YAML parser knows it is an octal number
                                   (like `0644' or `01777') or quote it (like `'644'' or `'1777'') so
                                   Ansible receives a string and can do its own conversion from string
                                   into number. Giving Ansible a number without following one of these
                                   rules will end up with a decimal number which will have unexpected
                                   results. As of Ansible 1.8, the mode may be specified as a symbolic
                                   mode (for example, `u+rwx' or `u=rw,g=r,o=r'). As of Ansible 2.6, the
                                   mode may also be the special string `preserve'. When set to `preserve'
                                   the file will be given the same permissions as the source file.
          modification_time:     # This parameter indicates the time the file's modification time should be set to. Should be `preserve'
                                   when no modification is required, `YYYYMMDDHHMM.SS' when using default
                                   time format, or `now'. Default is None meaning that `preserve' is the
                                   default for `state=[file,directory,link,hard]' and `now' is default
                                   for `state=touch'.
          modification_time_format:   # When used with `modification_time', indicates the time format that must be used. Based on default
                                   Python format (see time.strftime doc).
          owner:                 # Name of the user that should own the file/directory, as would be fed to `chown'.
          path:                  # (required) Path to the file being managed.
          recurse:               # Recursively set the specified file attributes on directory contents. This applies only when `state'
                                   is set to `directory'.
          selevel:               # The level part of the SELinux file context. This is the MLS/MCS attribute, sometimes known as the
                                   `range'. When set to `_default', it will use the `level' portion of
                                   the policy if available.
          serole:                # The role part of the SELinux file context. When set to `_default', it will use the `role' portion of
                                   the policy if available.
          setype:                # The type part of the SELinux file context. When set to `_default', it will use the `type' portion of
                                   the policy if available.
          seuser:                # The user part of the SELinux file context. By default it uses the `system' policy, where applicable.
                                   When set to `_default', it will use the `user' portion of the policy
                                   if available.
          src:                   # Path of the file to link to. This applies only to `state=link' and `state=hard'. For `state=link',
                                   this will also accept a non-existing path. Relative paths are relative
                                   to the file being created (`path') which is how the Unix command `ln
                                   -s SRC DEST' treats relative paths.
          state:                 # If `absent', directories will be recursively deleted, and files or symlinks will be unlinked. In the
                                   case of a directory, if `diff' is declared, you will see the files and
                                   folders deleted listed under `path_contents'. Note that `absent' will
                                   not cause `file' to fail if the `path' does not exist as the state did
                                   not change. If `directory', all intermediate subdirectories will be
                                   created if they do not exist. Since Ansible 1.7 they will be created
                                   with the supplied permissions. If `file', without any other options
                                   this works mostly as a 'stat' and will return the current state of
                                   `path'. Even with other options (i.e `mode'), the file will be
                                   modified but will NOT be created if it does not exist; see the `touch'
                                   value or the [copy] or [template] module if you want that behavior. If
                                   `hard', the hard link will be created or changed. If `link', the
                                   symbolic link will be created or changed. If `touch' (new in 1.4), an
                                   empty file will be created if the `path' does not exist, while an
                                   existing file or directory will receive updated file access and
                                   modification times (similar to the way `touch' works from the command
                                   line).
          unsafe_writes:         # Influence when to use atomic operation to prevent data corruption or inconsistent reads from the
                                   target file. By default this module uses atomic operations to prevent
                                   data corruption or inconsistent reads from the target files, but
                                   sometimes systems are configured or just broken in ways that prevent
                                   this. One example is docker mounted files, which cannot be updated
                                   atomically from inside the container and can only be written in an
                                   unsafe manner. This option allows Ansible to fall back to unsafe
                                   methods of updating files when atomic operations fail (however, it
                                   doesn't force Ansible to perform unsafe writes). IMPORTANT! Unsafe
                                   writes are subject to race conditions and can lead to data corruption.
    
    1. 实战
    [root@m01 ~]# ansible oldboy -m file -a "dest=/tmp/oldboy state=directory"
    172.16.1.41 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "gid": 0, 
        "group": "root", 
        "mode": "0755", 
        "owner": "root", 
        "path": "/tmp/oldboy", 
        "size": 6, 
        "state": "directory", 
        "uid": 0
    }
    172.16.1.31 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "gid": 0, 
        "group": "root", 
        "mode": "0755", 
        "owner": "root", 
        "path": "/tmp/oldboy", 
        "size": 6, 
        "state": "directory", 
        "uid": 0
    }
    
    1. 模块对比
    创建目录:mkdir /tmp/oldboy_dir
    ansible oldboy -m file -a "dest=/tmp/oldboy_dir state=directory"
    
    递归设置权限:
    ansible oldboy -m file -a "dest=/tmp/oldboy_dir state=directory mode=644 recurse=yes"
    
    创建文件:touch /tmp/oldboy_file
    ansible oldboy -m file -a "dest=/tmp/oldboy_file state=touch"
    
    删除文件:rm -f /tmp/oldboy_file
    ansible oldboy -m file -a "dest=/tmp/oldboy_file state=absent"
    
    创建链接文件:ln -s /etc/hosts /tmp/link_file
    ansible oldboy -m file -a "src=/etc/hosts dest=/tmp/link_file state=link"
    
    [root@m01 ~]# ansible oldboy -m shell -a "chmod 700 /tmp/oldboy warn=false"
    172.16.1.41 | CHANGED | rc=0 >>
    
    172.16.1.31 | CHANGED | rc=0 >>
    
    1. recurse 递归创建默认是no
    [root@m01 ~]# ansible oldboy -m file -a "dest=/tmp/oldboy/A/C/B state=directory recurse=yes"
    172.16.1.41 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "gid": 0, 
        "group": "root", 
        "mode": "0755", 
        "owner": "root", 
        "path": "/tmp/oldboy/A/C/B", 
        "size": 6, 
        "state": "directory", 
        "uid": 0
    }
    172.16.1.31 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "gid": 0, 
        "group": "root", 
        "mode": "0755", 
        "owner": "root", 
        "path": "/tmp/oldboy/A/C/B", 
        "size": 6, 
        "state": "directory", 
        "uid": 0
    }
    

    3.1.8 YUM 模块 YUM包管理模块

    1. YUM 参数
    [root@m01 ~]# ansible-doc -s yum
    - name: Manages packages with the `yum' package manager
      yum:
          allow_downgrade:       # Specify if the named package and version is allowed to downgrade a maybe already installed higher
                                   version of that package. Note that setting allow_downgrade=True can
                                   make this module behave in a non-idempotent way. The task could end up
                                   with a set of packages that does not match the complete list of
                                   specified packages to install (because dependencies between the
                                   downgraded package and others can cause changes to the packages which
                                   were in the earlier transaction).
          autoremove:            # If `yes', removes all "leaf" packages from the system that were originally installed as dependencies
                                   of user-installed packages but which are no longer required by any
                                   such package. Should be used alone or when state is `absent' NOTE:
                                   This feature requires yum >= 3.4.3 (RHEL/CentOS 7+)
          bugfix:                # If set to `yes', and `state=latest' then only installs updates that have been marked bugfix related.
          conf_file:             # The remote yum configuration file to use for the transaction.
          disable_excludes:      # Disable the excludes defined in YUM config files. If set to `all', disables all excludes. If set to
                                   `main', disable excludes defined in [main] in yum.conf. If set to
                                   `repoid', disable excludes defined for given repo id.
          disable_gpg_check:     # Whether to disable the GPG checking of signatures of packages being installed. Has an effect only if
                                   state is `present' or `latest'.
          disable_plugin:        # `Plugin' name to disable for the install/update operation. The disabled plugins will not persist
                                   beyond the transaction.
          disablerepo:           # `Repoid' of repositories to disable for the install/update operation. These repos will not persist
                                   beyond the transaction. When specifying multiple repos, separate them
                                   with a `","'. As of Ansible 2.7, this can alternatively be a list
                                   instead of `","' separated string
          download_dir:          # Specifies an alternate directory to store packages. Has an effect only if `download_only' is
                                   specified.
          download_only:         # Only download the packages, do not install them.
          enable_plugin:         # `Plugin' name to enable for the install/update operation. The enabled plugin will not persist beyond
                                   the transaction.
          enablerepo:            # `Repoid' of repositories to enable for the install/update operation. These repos will not persist
                                   beyond the transaction. When specifying multiple repos, separate them
                                   with a `","'. As of Ansible 2.7, this can alternatively be a list
                                   instead of `","' separated string
          exclude:               # Package name(s) to exclude when state=present, or latest
          install_weak_deps:     # Will also install all packages linked by a weak dependency relation. NOTE: This feature requires yum
                                   >= 4 (RHEL/CentOS 8+)
          installroot:           # Specifies an alternative installroot, relative to which all packages will be installed.
          list:                  # Package name to run the equivalent of yum list --show-duplicates <package> against. In addition to
                                   listing packages, use can also list the following: `installed',
                                   `updates', `available' and `repos'. This parameter is mutually
                                   exclusive with `name'.
          lock_timeout:          # Amount of time to wait for the yum lockfile to be freed.
          name:                  # A package name or package specifier with version, like `name-1.0'. If a previous version is
                                   specified, the task also needs to turn `allow_downgrade' on. See the
                                   `allow_downgrade' documentation for caveats with downgrading packages.
                                   When using state=latest, this can be `'*'' which means run `yum -y
                                   update'. You can also pass a url or a local path to a rpm file (using
                                   state=present). To operate on several packages this can accept a comma
                                   separated string of packages or (as of 2.0) a list of packages.
          releasever:            # Specifies an alternative release from which all packages will be installed.
          security:              # If set to `yes', and `state=latest' then only installs updates that have been marked security
                                   related.
          skip_broken:           # Skip packages with broken dependencies(devsolve) and are causing problems.
          state:                 # Whether to install (`present' or `installed', `latest'), or remove (`absent' or `removed') a package.
                                   `present' and `installed' will simply ensure that a desired package is
                                   installed. `latest' will update the specified package if it's not of
                                   the latest available version. `absent' and `removed' will remove the
                                   specified package. Default is `None', however in effect the default
                                   action is `present' unless the `autoremove' option is enabled for this
                                   module, then `absent' is inferred.
          update_cache:          # Force yum to check if cache is out of date and redownload if needed. Has an effect only if state is
                                   `present' or `latest'.
          update_only:           # When using latest, only update installed packages. Do not install packages. Has an effect only if
                                   state is `latest'
          use_backend:           # This module supports `yum' (as it always has), this is known as `yum3'/`YUM3'/`yum-deprecated' by
                                   upstream yum developers. As of Ansible 2.7+, this module also supports
                                   `YUM4', which is the "new yum" and it has an `dnf' backend. By
                                   default, this module will select the backend based on the
                                   `ansible_pkg_mgr' fact.
          validate_certs:        # This only applies if using a https url as the source of the rpm. e.g. for localinstall. If set to
                                   `no', the SSL certificates will not be validated. This should only set
                                   to `no' used on personally controlled sites using self-signed
                                   certificates as it avoids verifying the source site. Prior to 2.1 the
                                   code worked as if this was set to `yes'.
    
    1. 实战
    [root@m01 ~]# ansible oldboy -m yum  -a "name=nginx state=installed"
    172.16.1.31 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "changes": {
            "installed": [
                "nginx"
            ]
        }, 
        "msg": "", 
        "rc": 0, 
        "results": [
            "Loaded plugins: fastestmirror
    Loading mirror speeds from cached hostfile
     * epel: mirrors.bfsu.edu.cn
    Resolving Dependencies
    --> Running transaction check
    ---> Package nginx.x86_64 1:1.16.1-1.el7 will be installed
    --> Processing Dependency: nginx-all-modules = 1:1.16.1-1.el7 for package: 1:nginx-1.16.1-1.el7.x86_64
    --> Processing Dependency: nginx-filesystem = 1:1.16.1-1.el7 for package: 1:nginx-1.16.1-1.el7.x86_64
    --> Processing Dependency: nginx-filesystem for package: 1:nginx-1.16.1-1.el7.x86_64
    --> Processing Dependency: redhat-indexhtml for package: 1:nginx-1.16.1-1.el7.x86_64
    --> Processing Dependency: libprofiler.so.0()(64bit) for package: 1:nginx-1.16.1-1.el7.x86_64
    --> Running transaction check
    ---> Package centos-indexhtml.noarch 0:7-9.el7.centos will be installed
    ---> Package gperftools-libs.x86_64 0:2.6.1-1.el7 will be installed
    ---> Package nginx-all-modules.noarch 1:1.16.1-1.el7 will be installed
    --> Processing Dependency: nginx-mod-http-image-filter = 1:1.16.1-1.el7 for package: 1:nginx-all-modules-1.16.1-1.el7.noarch
    --> Processing Dependency: nginx-mod-http-perl = 1:1.16.1-1.el7 for package: 1:nginx-all-modules-1.16.1-1.el7.noarch
    --> Processing Dependency: nginx-mod-http-xslt-filter = 1:1.16.1-1.el7 for package: 1:nginx-all-modules-1.16.1-1.el7.noarch
    --> Processing Dependency: nginx-mod-mail = 1:1.16.1-1.el7 for package: 1:nginx-all-modules-1.16.1-1.el7.noarch
    --> Processing Dependency: nginx-mod-stream = 1:1.16.1-1.el7 for package: 1:nginx-all-modules-1.16.1-1.el7.noarch
    ---> Package nginx-filesystem.noarch 1:1.16.1-1.el7 will be installed
    --> Running transaction check
    ---> Package nginx-mod-http-image-filter.x86_64 1:1.16.1-1.el7 will be installed
    --> Processing Dependency: gd for package: 1:nginx-mod-http-image-filter-1.16.1-1.el7.x86_64
    --> Processing Dependency: libgd.so.2()(64bit) for package: 1:nginx-mod-http-image-filter-1.16.1-1.el7.x86_64
    ---> Package nginx-mod-http-perl.x86_64 1:1.16.1-1.el7 will be installed
    ---> Package nginx-mod-http-xslt-filter.x86_64 1:1.16.1-1.el7 will be installed
    ---> Package nginx-mod-mail.x86_64 1:1.16.1-1.el7 will be installed
    ---> Package nginx-mod-stream.x86_64 1:1.16.1-1.el7 will be installed
    --> Running transaction check
    ---> Package gd.x86_64 0:2.0.35-26.el7 will be installed
    --> Processing Dependency: libfontconfig.so.1()(64bit) for package: gd-2.0.35-26.el7.x86_64
    --> Processing Dependency: libXpm.so.4()(64bit) for package: gd-2.0.35-26.el7.x86_64
    --> Processing Dependency: libX11.so.6()(64bit) for package: gd-2.0.35-26.el7.x86_64
    --> Running transaction check
    ---> Package fontconfig.x86_64 0:2.13.0-4.3.el7 will be installed
    --> Processing Dependency: fontpackages-filesystem for package: fontconfig-2.13.0-4.3.el7.x86_64
    --> Processing Dependency: dejavu-sans-fonts for package: fontconfig-2.13.0-4.3.el7.x86_64
    ---> Package libX11.x86_64 0:1.6.7-2.el7 will be installed
    --> Processing Dependency: libX11-common >= 1.6.7-2.el7 for package: libX11-1.6.7-2.el7.x86_64
    --> Processing Dependency: libxcb.so.1()(64bit) for package: libX11-1.6.7-2.el7.x86_64
    ---> Package libXpm.x86_64 0:3.5.12-1.el7 will be installed
    --> Running transaction check
    ---> Package dejavu-sans-fonts.noarch 0:2.33-6.el7 will be installed
    --> Processing Dependency: dejavu-fonts-common = 2.33-6.el7 for package: dejavu-sans-fonts-2.33-6.el7.noarch
    ---> Package fontpackages-filesystem.noarch 0:1.44-8.el7 will be installed
    ---> Package libX11-common.noarch 0:1.6.7-2.el7 will be installed
    ---> Package libxcb.x86_64 0:1.13-1.el7 will be installed
    --> Processing Dependency: libXau.so.6()(64bit) for package: libxcb-1.13-1.el7.x86_64
    --> Running transaction check
    ---> Package dejavu-fonts-common.noarch 0:2.33-6.el7 will be installed
    ---> Package libXau.x86_64 0:1.0.8-2.1.el7 will be installed
    --> Finished Dependency Resolution
    
    Dependencies Resolved
    
    ================================================================================
     Package                         Arch       Version              Repository
                                                                               Size
    ================================================================================
    Installing:
     nginx                           x86_64     1:1.16.1-1.el7       epel     562 k
    Installing for dependencies:
     centos-indexhtml                noarch     7-9.el7.centos       base      92 k
     dejavu-fonts-common             noarch     2.33-6.el7           base      64 k
     dejavu-sans-fonts               noarch     2.33-6.el7           base     1.4 M
     fontconfig                      x86_64     2.13.0-4.3.el7       base     254 k
     fontpackages-filesystem         noarch     1.44-8.el7           base     9.9 k
     gd                              x86_64     2.0.35-26.el7        base     146 k
     gperftools-libs                 x86_64     2.6.1-1.el7          base     272 k
     libX11                          x86_64     1.6.7-2.el7          base     607 k
     libX11-common                   noarch     1.6.7-2.el7          base     164 k
     libXau                          x86_64     1.0.8-2.1.el7        base      29 k
     libXpm                          x86_64     3.5.12-1.el7         base      55 k
     libxcb                          x86_64     1.13-1.el7           base     214 k
     nginx-all-modules               noarch     1:1.16.1-1.el7       epel      19 k
     nginx-filesystem                noarch     1:1.16.1-1.el7       epel      21 k
     nginx-mod-http-image-filter     x86_64     1:1.16.1-1.el7       epel      30 k
     nginx-mod-http-perl             x86_64     1:1.16.1-1.el7       epel      39 k
     nginx-mod-http-xslt-filter      x86_64     1:1.16.1-1.el7       epel      29 k
     nginx-mod-mail                  x86_64     1:1.16.1-1.el7       epel      57 k
     nginx-mod-stream                x86_64     1:1.16.1-1.el7       epel      84 k
    
    Transaction Summary
    ================================================================================
    Install  1 Package (+19 Dependent packages)
    
    Total download size: 4.1 M
    Installed size: 14 M
    Downloading packages:
    --------------------------------------------------------------------------------
    Total                                              1.0 MB/s | 4.1 MB  00:04     
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
      Installing : fontpackages-filesystem-1.44-8.el7.noarch                   1/20 
      Installing : dejavu-fonts-common-2.33-6.el7.noarch                       2/20 
      Installing : dejavu-sans-fonts-2.33-6.el7.noarch                         3/20 
      Installing : fontconfig-2.13.0-4.3.el7.x86_64                            4/20 
      Installing : centos-indexhtml-7-9.el7.centos.noarch                      5/20 
      Installing : libX11-common-1.6.7-2.el7.noarch                            6/20 
      Installing : gperftools-libs-2.6.1-1.el7.x86_64                          7/20 
      Installing : libXau-1.0.8-2.1.el7.x86_64                                 8/20 
      Installing : libxcb-1.13-1.el7.x86_64                                    9/20 
      Installing : libX11-1.6.7-2.el7.x86_64                                  10/20 
      Installing : libXpm-3.5.12-1.el7.x86_64                                 11/20 
      Installing : gd-2.0.35-26.el7.x86_64                                    12/20 
      Installing : 1:nginx-filesystem-1.16.1-1.el7.noarch                     13/20 
      Installing : 1:nginx-mod-stream-1.16.1-1.el7.x86_64                     14/20 
      Installing : 1:nginx-mod-http-perl-1.16.1-1.el7.x86_64                  15/20 
      Installing : 1:nginx-mod-mail-1.16.1-1.el7.x86_64                       16/20 
      Installing : 1:nginx-mod-http-xslt-filter-1.16.1-1.el7.x86_64           17/20 
      Installing : 1:nginx-1.16.1-1.el7.x86_64                                18/20 
      Installing : 1:nginx-mod-http-image-filter-1.16.1-1.el7.x86_64          19/20 
      Installing : 1:nginx-all-modules-1.16.1-1.el7.noarch                    20/20 
      Verifying  : libXpm-3.5.12-1.el7.x86_64                                  1/20 
      Verifying  : 1:nginx-mod-stream-1.16.1-1.el7.x86_64                      2/20 
      Verifying  : fontconfig-2.13.0-4.3.el7.x86_64                            3/20 
      Verifying  : libxcb-1.13-1.el7.x86_64                                    4/20 
      Verifying  : dejavu-sans-fonts-2.33-6.el7.noarch                         5/20 
      Verifying  : 1:nginx-filesystem-1.16.1-1.el7.noarch                      6/20 
      Verifying  : libXau-1.0.8-2.1.el7.x86_64                                 7/20 
      Verifying  : fontpackages-filesystem-1.44-8.el7.noarch                   8/20 
      Verifying  : gperftools-libs-2.6.1-1.el7.x86_64                          9/20 
      Verifying  : dejavu-fonts-common-2.33-6.el7.noarch                      10/20 
      Verifying  : 1:nginx-mod-http-perl-1.16.1-1.el7.x86_64                  11/20 
      Verifying  : 1:nginx-1.16.1-1.el7.x86_64                                12/20 
      Verifying  : libX11-common-1.6.7-2.el7.noarch                           13/20 
      Verifying  : 1:nginx-mod-mail-1.16.1-1.el7.x86_64                       14/20 
      Verifying  : 1:nginx-all-modules-1.16.1-1.el7.noarch                    15/20 
      Verifying  : gd-2.0.35-26.el7.x86_64                                    16/20 
      Verifying  : 1:nginx-mod-http-xslt-filter-1.16.1-1.el7.x86_64           17/20 
      Verifying  : libX11-1.6.7-2.el7.x86_64                                  18/20 
      Verifying  : centos-indexhtml-7-9.el7.centos.noarch                     19/20 
      Verifying  : 1:nginx-mod-http-image-filter-1.16.1-1.el7.x86_64          20/20 
    
    Installed:
      nginx.x86_64 1:1.16.1-1.el7                                                   
    
    Dependency Installed:
      centos-indexhtml.noarch 0:7-9.el7.centos                                      
      dejavu-fonts-common.noarch 0:2.33-6.el7                                       
      dejavu-sans-fonts.noarch 0:2.33-6.el7                                         
      fontconfig.x86_64 0:2.13.0-4.3.el7                                            
      fontpackages-filesystem.noarch 0:1.44-8.el7                                   
      gd.x86_64 0:2.0.35-26.el7                                                     
      gperftools-libs.x86_64 0:2.6.1-1.el7                                          
      libX11.x86_64 0:1.6.7-2.el7                                                   
      libX11-common.noarch 0:1.6.7-2.el7                                            
      libXau.x86_64 0:1.0.8-2.1.el7                                                 
      libXpm.x86_64 0:3.5.12-1.el7                                                  
      libxcb.x86_64 0:1.13-1.el7                                                    
      nginx-all-modules.noarch 1:1.16.1-1.el7                                       
      nginx-filesystem.noarch 1:1.16.1-1.el7                                        
      nginx-mod-http-image-filter.x86_64 1:1.16.1-1.el7                             
      nginx-mod-http-perl.x86_64 1:1.16.1-1.el7                                     
      nginx-mod-http-xslt-filter.x86_64 1:1.16.1-1.el7                              
      nginx-mod-mail.x86_64 1:1.16.1-1.el7                                          
      nginx-mod-stream.x86_64 1:1.16.1-1.el7                                        
    
    Complete!
    "
        ]
    }
    172.16.1.41 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "changes": {
            "installed": [
                "nginx"
            ]
        }, 
        "msg": "", 
        "rc": 0, 
        "results": [
            "Loaded plugins: fastestmirror
    Loading mirror speeds from cached hostfile
     * epel: mirror.poliwangi.ac.id
    Resolving Dependencies
    --> Running transaction check
    ---> Package nginx.x86_64 1:1.16.1-1.el7 will be installed
    --> Processing Dependency: nginx-all-modules = 1:1.16.1-1.el7 for package: 1:nginx-1.16.1-1.el7.x86_64
    --> Processing Dependency: nginx-filesystem = 1:1.16.1-1.el7 for package: 1:nginx-1.16.1-1.el7.x86_64
    --> Processing Dependency: nginx-filesystem for package: 1:nginx-1.16.1-1.el7.x86_64
    --> Processing Dependency: redhat-indexhtml for package: 1:nginx-1.16.1-1.el7.x86_64
    --> Processing Dependency: libprofiler.so.0()(64bit) for package: 1:nginx-1.16.1-1.el7.x86_64
    --> Running transaction check
    ---> Package centos-indexhtml.noarch 0:7-9.el7.centos will be installed
    ---> Package gperftools-libs.x86_64 0:2.6.1-1.el7 will be installed
    ---> Package nginx-all-modules.noarch 1:1.16.1-1.el7 will be installed
    --> Processing Dependency: nginx-mod-http-image-filter = 1:1.16.1-1.el7 for package: 1:nginx-all-modules-1.16.1-1.el7.noarch
    --> Processing Dependency: nginx-mod-http-perl = 1:1.16.1-1.el7 for package: 1:nginx-all-modules-1.16.1-1.el7.noarch
    --> Processing Dependency: nginx-mod-http-xslt-filter = 1:1.16.1-1.el7 for package: 1:nginx-all-modules-1.16.1-1.el7.noarch
    --> Processing Dependency: nginx-mod-mail = 1:1.16.1-1.el7 for package: 1:nginx-all-modules-1.16.1-1.el7.noarch
    --> Processing Dependency: nginx-mod-stream = 1:1.16.1-1.el7 for package: 1:nginx-all-modules-1.16.1-1.el7.noarch
    ---> Package nginx-filesystem.noarch 1:1.16.1-1.el7 will be installed
    --> Running transaction check
    ---> Package nginx-mod-http-image-filter.x86_64 1:1.16.1-1.el7 will be installed
    --> Processing Dependency: gd for package: 1:nginx-mod-http-image-filter-1.16.1-1.el7.x86_64
    --> Processing Dependency: libgd.so.2()(64bit) for package: 1:nginx-mod-http-image-filter-1.16.1-1.el7.x86_64
    ---> Package nginx-mod-http-perl.x86_64 1:1.16.1-1.el7 will be installed
    ---> Package nginx-mod-http-xslt-filter.x86_64 1:1.16.1-1.el7 will be installed
    ---> Package nginx-mod-mail.x86_64 1:1.16.1-1.el7 will be installed
    ---> Package nginx-mod-stream.x86_64 1:1.16.1-1.el7 will be installed
    --> Running transaction check
    ---> Package gd.x86_64 0:2.0.35-26.el7 will be installed
    --> Processing Dependency: libfontconfig.so.1()(64bit) for package: gd-2.0.35-26.el7.x86_64
    --> Processing Dependency: libXpm.so.4()(64bit) for package: gd-2.0.35-26.el7.x86_64
    --> Processing Dependency: libX11.so.6()(64bit) for package: gd-2.0.35-26.el7.x86_64
    --> Running transaction check
    ---> Package fontconfig.x86_64 0:2.13.0-4.3.el7 will be installed
    --> Processing Dependency: fontpackages-filesystem for package: fontconfig-2.13.0-4.3.el7.x86_64
    --> Processing Dependency: dejavu-sans-fonts for package: fontconfig-2.13.0-4.3.el7.x86_64
    ---> Package libX11.x86_64 0:1.6.7-2.el7 will be installed
    --> Processing Dependency: libX11-common >= 1.6.7-2.el7 for package: libX11-1.6.7-2.el7.x86_64
    --> Processing Dependency: libxcb.so.1()(64bit) for package: libX11-1.6.7-2.el7.x86_64
    ---> Package libXpm.x86_64 0:3.5.12-1.el7 will be installed
    --> Running transaction check
    ---> Package dejavu-sans-fonts.noarch 0:2.33-6.el7 will be installed
    --> Processing Dependency: dejavu-fonts-common = 2.33-6.el7 for package: dejavu-sans-fonts-2.33-6.el7.noarch
    ---> Package fontpackages-filesystem.noarch 0:1.44-8.el7 will be installed
    ---> Package libX11-common.noarch 0:1.6.7-2.el7 will be installed
    ---> Package libxcb.x86_64 0:1.13-1.el7 will be installed
    --> Processing Dependency: libXau.so.6()(64bit) for package: libxcb-1.13-1.el7.x86_64
    --> Running transaction check
    ---> Package dejavu-fonts-common.noarch 0:2.33-6.el7 will be installed
    ---> Package libXau.x86_64 0:1.0.8-2.1.el7 will be installed
    --> Finished Dependency Resolution
    
    Dependencies Resolved
    
    ================================================================================
     Package                         Arch       Version              Repository
                                                                               Size
    ================================================================================
    Installing:
     nginx                           x86_64     1:1.16.1-1.el7       epel     562 k
    Installing for dependencies:
     centos-indexhtml                noarch     7-9.el7.centos       base      92 k
     dejavu-fonts-common             noarch     2.33-6.el7           base      64 k
     dejavu-sans-fonts               noarch     2.33-6.el7           base     1.4 M
     fontconfig                      x86_64     2.13.0-4.3.el7       base     254 k
     fontpackages-filesystem         noarch     1.44-8.el7           base     9.9 k
     gd                              x86_64     2.0.35-26.el7        base     146 k
     gperftools-libs                 x86_64     2.6.1-1.el7          base     272 k
     libX11                          x86_64     1.6.7-2.el7          base     607 k
     libX11-common                   noarch     1.6.7-2.el7          base     164 k
     libXau                          x86_64     1.0.8-2.1.el7        base      29 k
     libXpm                          x86_64     3.5.12-1.el7         base      55 k
     libxcb                          x86_64     1.13-1.el7           base     214 k
     nginx-all-modules               noarch     1:1.16.1-1.el7       epel      19 k
     nginx-filesystem                noarch     1:1.16.1-1.el7       epel      21 k
     nginx-mod-http-image-filter     x86_64     1:1.16.1-1.el7       epel      30 k
     nginx-mod-http-perl             x86_64     1:1.16.1-1.el7       epel      39 k
     nginx-mod-http-xslt-filter      x86_64     1:1.16.1-1.el7       epel      29 k
     nginx-mod-mail                  x86_64     1:1.16.1-1.el7       epel      57 k
     nginx-mod-stream                x86_64     1:1.16.1-1.el7       epel      84 k
    
    Transaction Summary
    ================================================================================
    Install  1 Package (+19 Dependent packages)
    
    Total download size: 4.1 M
    Installed size: 14 M
    Downloading packages:
    --------------------------------------------------------------------------------
    Total                                              607 kB/s | 4.1 MB  00:06     
    Running transaction check
    Running transaction test
    Transaction test succeeded
    Running transaction
      Installing : fontpackages-filesystem-1.44-8.el7.noarch                   1/20 
      Installing : dejavu-fonts-common-2.33-6.el7.noarch                       2/20 
      Installing : dejavu-sans-fonts-2.33-6.el7.noarch                         3/20 
      Installing : fontconfig-2.13.0-4.3.el7.x86_64                            4/20 
      Installing : centos-indexhtml-7-9.el7.centos.noarch                      5/20 
      Installing : libX11-common-1.6.7-2.el7.noarch                            6/20 
      Installing : gperftools-libs-2.6.1-1.el7.x86_64                          7/20 
      Installing : libXau-1.0.8-2.1.el7.x86_64                                 8/20 
      Installing : libxcb-1.13-1.el7.x86_64                                    9/20 
      Installing : libX11-1.6.7-2.el7.x86_64                                  10/20 
      Installing : libXpm-3.5.12-1.el7.x86_64                                 11/20 
      Installing : gd-2.0.35-26.el7.x86_64                                    12/20 
      Installing : 1:nginx-filesystem-1.16.1-1.el7.noarch                     13/20 
      Installing : 1:nginx-mod-stream-1.16.1-1.el7.x86_64                     14/20 
      Installing : 1:nginx-mod-http-perl-1.16.1-1.el7.x86_64                  15/20 
      Installing : 1:nginx-mod-mail-1.16.1-1.el7.x86_64                       16/20 
      Installing : 1:nginx-mod-http-xslt-filter-1.16.1-1.el7.x86_64           17/20 
      Installing : 1:nginx-1.16.1-1.el7.x86_64                                18/20 
      Installing : 1:nginx-mod-http-image-filter-1.16.1-1.el7.x86_64          19/20 
      Installing : 1:nginx-all-modules-1.16.1-1.el7.noarch                    20/20 
      Verifying  : libXpm-3.5.12-1.el7.x86_64                                  1/20 
      Verifying  : 1:nginx-mod-stream-1.16.1-1.el7.x86_64                      2/20 
      Verifying  : fontconfig-2.13.0-4.3.el7.x86_64                            3/20 
      Verifying  : libxcb-1.13-1.el7.x86_64                                    4/20 
      Verifying  : dejavu-sans-fonts-2.33-6.el7.noarch                         5/20 
      Verifying  : 1:nginx-filesystem-1.16.1-1.el7.noarch                      6/20 
      Verifying  : libXau-1.0.8-2.1.el7.x86_64                                 7/20 
      Verifying  : fontpackages-filesystem-1.44-8.el7.noarch                   8/20 
      Verifying  : gperftools-libs-2.6.1-1.el7.x86_64                          9/20 
      Verifying  : dejavu-fonts-common-2.33-6.el7.noarch                      10/20 
      Verifying  : 1:nginx-mod-http-perl-1.16.1-1.el7.x86_64                  11/20 
      Verifying  : 1:nginx-1.16.1-1.el7.x86_64                                12/20 
      Verifying  : libX11-common-1.6.7-2.el7.noarch                           13/20 
      Verifying  : 1:nginx-mod-mail-1.16.1-1.el7.x86_64                       14/20 
      Verifying  : 1:nginx-all-modules-1.16.1-1.el7.noarch                    15/20 
      Verifying  : gd-2.0.35-26.el7.x86_64                                    16/20 
      Verifying  : 1:nginx-mod-http-xslt-filter-1.16.1-1.el7.x86_64           17/20 
      Verifying  : libX11-1.6.7-2.el7.x86_64                                  18/20 
      Verifying  : centos-indexhtml-7-9.el7.centos.noarch                     19/20 
      Verifying  : 1:nginx-mod-http-image-filter-1.16.1-1.el7.x86_64          20/20 
    
    Installed:
      nginx.x86_64 1:1.16.1-1.el7                                                   
    
    Dependency Installed:
      centos-indexhtml.noarch 0:7-9.el7.centos                                      
      dejavu-fonts-common.noarch 0:2.33-6.el7                                       
      dejavu-sans-fonts.noarch 0:2.33-6.el7                                         
      fontconfig.x86_64 0:2.13.0-4.3.el7                                            
      fontpackages-filesystem.noarch 0:1.44-8.el7                                   
      gd.x86_64 0:2.0.35-26.el7                                                     
      gperftools-libs.x86_64 0:2.6.1-1.el7                                          
      libX11.x86_64 0:1.6.7-2.el7                                                   
      libX11-common.noarch 0:1.6.7-2.el7                                            
      libXau.x86_64 0:1.0.8-2.1.el7                                                 
      libXpm.x86_64 0:3.5.12-1.el7                                                  
      libxcb.x86_64 0:1.13-1.el7                                                    
      nginx-all-modules.noarch 1:1.16.1-1.el7                                       
      nginx-filesystem.noarch 1:1.16.1-1.el7                                        
      nginx-mod-http-image-filter.x86_64 1:1.16.1-1.el7                             
      nginx-mod-http-perl.x86_64 1:1.16.1-1.el7                                     
      nginx-mod-http-xslt-filter.x86_64 1:1.16.1-1.el7                              
      nginx-mod-mail.x86_64 1:1.16.1-1.el7                                          
      nginx-mod-stream.x86_64 1:1.16.1-1.el7                                        
    
    Complete!
    "
        ]
    }
    [root@m01 ~]# ansible oldboy -m yum  -a "name=nc state=installed"
    172.16.1.41 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "msg": "", 
        "rc": 0, 
        "results": [
            "2:nmap-ncat-6.40-19.el7.x86_64 providing nc is already installed"
        ]
    }
    172.16.1.31 | SUCCESS => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "msg": "", 
        "rc": 0, 
        "results": [
            "2:nmap-ncat-6.40-19.el7.x86_64 providing nc is already installed"
        ]
    }
    
    

    3.1.9 systemd 系统管理模块

    1.systemd 参数

    [root@m01 ~]# ansible-doc -s systemd
    - name: Manage services
      systemd:
          daemon_reexec:         # Run daemon_reexec command before doing any other operations, the systemd manager will serialize the
                                   manager state.
          daemon_reload:         # Run daemon-reload before doing any other operations, to make sure systemd has read any changes. When
                                   set to `yes', runs daemon-reload even if the module does not start or
                                   stop anything.
          enabled:               # Whether the service should start on boot. *At least one of state and enabled are required.*
          force:                 # Whether to override existing symlinks.
          masked:                # Whether the unit should be masked or not, a masked unit is impossible to start.
          name:                  # Name of the service. This parameter takes the name of exactly one service to work with. When using in
                                   a chroot environment you always need to specify the full name i.e.
                                   (crond.service).
          no_block:              # Do not synchronously wait for the requested operation to finish. Enqueued job will continue without
                                   Ansible blocking on its completion.
          scope:                 # run systemctl within a given service manager scope, either as the default system scope (system), the
                                   current user's scope (user), or the scope of all users (global). For
                                   systemd to work with 'user', the executing user must have its own
                                   instance of dbus started (systemd requirement). The user dbus process
                                   is normally started during normal login, but not during the run of
                                   Ansible tasks. Otherwise you will probably get a 'Failed to connect to
                                   bus: no such file or directory' error.
          state:                 # `started'/`stopped' are idempotent actions that will not run commands unless necessary. `restarted'
                                   will always bounce the service. `reloaded' will always reload.
          user:                  # (deprecated) run ``systemctl`` talking to the service manager of the calling user, rather than the
                                   service manager of the system. This option is deprecated and will
                                   eventually be removed in 2.11. The ``scope`` option should be used
                                   instead.
    
    1. 实战
    [root@m01 ~]# ansible oldboy -m systemd -a "name=crond enabled=no state=stopped"
    172.16.1.31 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "enabled": false, 
        "name": "crond", 
        "state": "stopped", 
        "status": {
            "ActiveEnterTimestamp": "Sun 2020-05-03 20:33:26 CST", 
            "ActiveEnterTimestampMonotonic": "116891956", 
            "ActiveExitTimestamp": "Sun 2020-05-03 20:33:26 CST", 
            "ActiveExitTimestampMonotonic": "116889033", 
            "ActiveState": "active", 
            "After": "auditd.service systemd-user-sessions.service basic.target system.slice systemd-journald.socket time-sync.target", 
            "AllowIsolate": "no", 
            "AmbientCapabilities": "0", 
            "AssertResult": "yes", 
            "AssertTimestamp": "Sun 2020-05-03 20:33:26 CST", 
            "AssertTimestampMonotonic": "116891239", 
            "Before": "multi-user.target shutdown.target", 
            "BlockIOAccounting": "no", 
            "BlockIOWeight": "18446744073709551615", 
            "CPUAccounting": "no", 
            "CPUQuotaPerSecUSec": "infinity", 
            "CPUSchedulingPolicy": "0", 
            "CPUSchedulingPriority": "0", 
            "CPUSchedulingResetOnFork": "no", 
            "CPUShares": "18446744073709551615", 
            "CanIsolate": "no", 
            "CanReload": "yes", 
            "CanStart": "yes", 
            "CanStop": "yes", 
            "CapabilityBoundingSet": "18446744073709551615", 
            "ConditionResult": "yes", 
            "ConditionTimestamp": "Sun 2020-05-03 20:33:26 CST", 
            "ConditionTimestampMonotonic": "116891238", 
            "Conflicts": "shutdown.target", 
            "ControlGroup": "/system.slice/crond.service", 
            "ControlPID": "0", 
            "DefaultDependencies": "yes", 
            "Delegate": "no", 
            "Description": "Command Scheduler", 
            "DevicePolicy": "auto", 
            "EnvironmentFile": "/etc/sysconfig/crond (ignore_errors=no)", 
            "ExecMainCode": "0", 
            "ExecMainExitTimestampMonotonic": "0", 
            "ExecMainPID": "1490", 
            "ExecMainStartTimestamp": "Sun 2020-05-03 20:33:26 CST", 
            "ExecMainStartTimestampMonotonic": "116891894", 
            "ExecMainStatus": "0", 
            "ExecReload": "{ path=/bin/kill ; argv[]=/bin/kill -HUP $MAINPID ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
            "ExecStart": "{ path=/usr/sbin/crond ; argv[]=/usr/sbin/crond -n $CRONDARGS ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
            "FailureAction": "none", 
            "FileDescriptorStoreMax": "0", 
            "FragmentPath": "/usr/lib/systemd/system/crond.service", 
            "GuessMainPID": "yes", 
            "IOScheduling": "0", 
            "Id": "crond.service", 
            "IgnoreOnIsolate": "no", 
            "IgnoreOnSnapshot": "no", 
            "IgnoreSIGPIPE": "yes", 
            "InactiveEnterTimestamp": "Sun 2020-05-03 20:33:26 CST", 
            "InactiveEnterTimestampMonotonic": "116890384", 
            "InactiveExitTimestamp": "Sun 2020-05-03 20:33:26 CST", 
            "InactiveExitTimestampMonotonic": "116891956", 
            "JobTimeoutAction": "none", 
            "JobTimeoutUSec": "0", 
            "KillMode": "process", 
            "KillSignal": "15", 
            "LimitAS": "18446744073709551615", 
            "LimitCORE": "18446744073709551615", 
            "LimitCPU": "18446744073709551615", 
            "LimitDATA": "18446744073709551615", 
            "LimitFSIZE": "18446744073709551615", 
            "LimitLOCKS": "18446744073709551615", 
            "LimitMEMLOCK": "65536", 
            "LimitMSGQUEUE": "819200", 
            "LimitNICE": "0", 
            "LimitNOFILE": "4096", 
            "LimitNPROC": "7828", 
            "LimitRSS": "18446744073709551615", 
            "LimitRTPRIO": "0", 
            "LimitRTTIME": "18446744073709551615", 
            "LimitSIGPENDING": "7828", 
            "LimitSTACK": "18446744073709551615", 
            "LoadState": "loaded", 
            "MainPID": "1490", 
            "MemoryAccounting": "no", 
            "MemoryCurrent": "18446744073709551615", 
            "MemoryLimit": "18446744073709551615", 
            "MountFlags": "0", 
            "Names": "crond.service", 
            "NeedDaemonReload": "no", 
            "Nice": "0", 
            "NoNewPrivileges": "no", 
            "NonBlocking": "no", 
            "NotifyAccess": "none", 
            "OOMScoreAdjust": "0", 
            "OnFailureJobMode": "replace", 
            "PermissionsStartOnly": "no", 
            "PrivateDevices": "no", 
            "PrivateNetwork": "no", 
            "PrivateTmp": "no", 
            "ProtectHome": "no", 
            "ProtectSystem": "no", 
            "RefuseManualStart": "no", 
            "RefuseManualStop": "no", 
            "RemainAfterExit": "no", 
            "Requires": "basic.target system.slice", 
            "Restart": "on-failure", 
            "RestartUSec": "30s", 
            "Result": "success", 
            "RootDirectoryStartOnly": "no", 
            "RuntimeDirectoryMode": "0755", 
            "SameProcessGroup": "no", 
            "SecureBits": "0", 
            "SendSIGHUP": "no", 
            "SendSIGKILL": "yes", 
            "Slice": "system.slice", 
            "StandardError": "inherit", 
            "StandardInput": "null", 
            "StandardOutput": "journal", 
            "StartLimitAction": "none", 
            "StartLimitBurst": "5", 
            "StartLimitInterval": "10000000", 
            "StartupBlockIOWeight": "18446744073709551615", 
            "StartupCPUShares": "18446744073709551615", 
            "StatusErrno": "0", 
            "StopWhenUnneeded": "no", 
            "SubState": "running", 
            "SyslogLevelPrefix": "yes", 
            "SyslogPriority": "30", 
            "SystemCallErrorNumber": "0", 
            "TTYReset": "no", 
            "TTYVHangup": "no", 
            "TTYVTDisallocate": "no", 
            "TasksAccounting": "no", 
            "TasksCurrent": "18446744073709551615", 
            "TasksMax": "18446744073709551615", 
            "TimeoutStartUSec": "1min 30s", 
            "TimeoutStopUSec": "1min 30s", 
            "TimerSlackNSec": "50000", 
            "Transient": "no", 
            "Type": "simple", 
            "UMask": "0022", 
            "UnitFilePreset": "enabled", 
            "UnitFileState": "enabled", 
            "WantedBy": "multi-user.target", 
            "WatchdogTimestamp": "Sun 2020-05-03 20:33:26 CST", 
            "WatchdogTimestampMonotonic": "116891937", 
            "WatchdogUSec": "0"
        }
    }
    172.16.1.41 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "enabled": false, 
        "name": "crond", 
        "state": "stopped", 
        "status": {
            "ActiveEnterTimestamp": "Sun 2020-05-03 20:33:05 CST", 
            "ActiveEnterTimestampMonotonic": "92344587", 
            "ActiveExitTimestamp": "Sun 2020-05-03 20:33:05 CST", 
            "ActiveExitTimestampMonotonic": "92341031", 
            "ActiveState": "active", 
            "After": "auditd.service basic.target systemd-user-sessions.service systemd-journald.socket system.slice time-sync.target", 
            "AllowIsolate": "no", 
            "AmbientCapabilities": "0", 
            "AssertResult": "yes", 
            "AssertTimestamp": "Sun 2020-05-03 20:33:05 CST", 
            "AssertTimestampMonotonic": "92343868", 
            "Before": "shutdown.target multi-user.target", 
            "BlockIOAccounting": "no", 
            "BlockIOWeight": "18446744073709551615", 
            "CPUAccounting": "no", 
            "CPUQuotaPerSecUSec": "infinity", 
            "CPUSchedulingPolicy": "0", 
            "CPUSchedulingPriority": "0", 
            "CPUSchedulingResetOnFork": "no", 
            "CPUShares": "18446744073709551615", 
            "CanIsolate": "no", 
            "CanReload": "yes", 
            "CanStart": "yes", 
            "CanStop": "yes", 
            "CapabilityBoundingSet": "18446744073709551615", 
            "ConditionResult": "yes", 
            "ConditionTimestamp": "Sun 2020-05-03 20:33:05 CST", 
            "ConditionTimestampMonotonic": "92343868", 
            "Conflicts": "shutdown.target", 
            "ControlGroup": "/system.slice/crond.service", 
            "ControlPID": "0", 
            "DefaultDependencies": "yes", 
            "Delegate": "no", 
            "Description": "Command Scheduler", 
            "DevicePolicy": "auto", 
            "EnvironmentFile": "/etc/sysconfig/crond (ignore_errors=no)", 
            "ExecMainCode": "0", 
            "ExecMainExitTimestampMonotonic": "0", 
            "ExecMainPID": "1473", 
            "ExecMainStartTimestamp": "Sun 2020-05-03 20:33:05 CST", 
            "ExecMainStartTimestampMonotonic": "92344539", 
            "ExecMainStatus": "0", 
            "ExecReload": "{ path=/bin/kill ; argv[]=/bin/kill -HUP $MAINPID ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
            "ExecStart": "{ path=/usr/sbin/crond ; argv[]=/usr/sbin/crond -n $CRONDARGS ; ignore_errors=no ; start_time=[n/a] ; stop_time=[n/a] ; pid=0 ; code=(null) ; status=0/0 }", 
            "FailureAction": "none", 
            "FileDescriptorStoreMax": "0", 
            "FragmentPath": "/usr/lib/systemd/system/crond.service", 
            "GuessMainPID": "yes", 
            "IOScheduling": "0", 
            "Id": "crond.service", 
            "IgnoreOnIsolate": "no", 
            "IgnoreOnSnapshot": "no", 
            "IgnoreSIGPIPE": "yes", 
            "InactiveEnterTimestamp": "Sun 2020-05-03 20:33:05 CST", 
            "InactiveEnterTimestampMonotonic": "92342564", 
            "InactiveExitTimestamp": "Sun 2020-05-03 20:33:05 CST", 
            "InactiveExitTimestampMonotonic": "92344587", 
            "JobTimeoutAction": "none", 
            "JobTimeoutUSec": "0", 
            "KillMode": "process", 
            "KillSignal": "15", 
            "LimitAS": "18446744073709551615", 
            "LimitCORE": "18446744073709551615", 
            "LimitCPU": "18446744073709551615", 
            "LimitDATA": "18446744073709551615", 
            "LimitFSIZE": "18446744073709551615", 
            "LimitLOCKS": "18446744073709551615", 
            "LimitMEMLOCK": "65536", 
            "LimitMSGQUEUE": "819200", 
            "LimitNICE": "0", 
            "LimitNOFILE": "4096", 
            "LimitNPROC": "7828", 
            "LimitRSS": "18446744073709551615", 
            "LimitRTPRIO": "0", 
            "LimitRTTIME": "18446744073709551615", 
            "LimitSIGPENDING": "7828", 
            "LimitSTACK": "18446744073709551615", 
            "LoadState": "loaded", 
            "MainPID": "1473", 
            "MemoryAccounting": "no", 
            "MemoryCurrent": "18446744073709551615", 
            "MemoryLimit": "18446744073709551615", 
            "MountFlags": "0", 
            "Names": "crond.service", 
            "NeedDaemonReload": "no", 
            "Nice": "0", 
            "NoNewPrivileges": "no", 
            "NonBlocking": "no", 
            "NotifyAccess": "none", 
            "OOMScoreAdjust": "0", 
            "OnFailureJobMode": "replace", 
            "PermissionsStartOnly": "no", 
            "PrivateDevices": "no", 
            "PrivateNetwork": "no", 
            "PrivateTmp": "no", 
            "ProtectHome": "no", 
            "ProtectSystem": "no", 
            "RefuseManualStart": "no", 
            "RefuseManualStop": "no", 
            "RemainAfterExit": "no", 
            "Requires": "basic.target system.slice", 
            "Restart": "on-failure", 
            "RestartUSec": "30s", 
            "Result": "success", 
            "RootDirectoryStartOnly": "no", 
            "RuntimeDirectoryMode": "0755", 
            "SameProcessGroup": "no", 
            "SecureBits": "0", 
            "SendSIGHUP": "no", 
            "SendSIGKILL": "yes", 
            "Slice": "system.slice", 
            "StandardError": "inherit", 
            "StandardInput": "null", 
            "StandardOutput": "journal", 
            "StartLimitAction": "none", 
            "StartLimitBurst": "5", 
            "StartLimitInterval": "10000000", 
            "StartupBlockIOWeight": "18446744073709551615", 
            "StartupCPUShares": "18446744073709551615", 
            "StatusErrno": "0", 
            "StopWhenUnneeded": "no", 
            "SubState": "running", 
            "SyslogLevelPrefix": "yes", 
            "SyslogPriority": "30", 
            "SystemCallErrorNumber": "0", 
            "TTYReset": "no", 
            "TTYVHangup": "no", 
            "TTYVTDisallocate": "no", 
            "TasksAccounting": "no", 
            "TasksCurrent": "18446744073709551615", 
            "TasksMax": "18446744073709551615", 
            "TimeoutStartUSec": "1min 30s", 
            "TimeoutStopUSec": "1min 30s", 
            "TimerSlackNSec": "50000", 
            "Transient": "no", 
            "Type": "simple", 
            "UMask": "0022", 
            "UnitFilePreset": "enabled", 
            "UnitFileState": "enabled", 
            "WantedBy": "multi-user.target", 
            "WatchdogTimestamp": "Sun 2020-05-03 20:33:05 CST", 
            "WatchdogTimestampMonotonic": "92344569", 
            "WatchdogUSec": "0"
        }
    }
    [root@m01 ~]# ansible oldboy -m shell -a "systemctl status crond"
    172.16.1.31 | FAILED | rc=3 >>
    ● crond.service - Command Scheduler
       Loaded: loaded (/usr/lib/systemd/system/crond.service; disabled; vendor preset: enabled)
       Active: inactive (dead)
    
    May 03 20:32:03 nfs01 crond[965]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 83% if used.)
    May 03 20:32:04 nfs01 crond[965]: (CRON) INFO (running with inotify support)
    May 03 20:33:26 nfs01 systemd[1]: Stopping Command Scheduler...
    May 03 20:33:26 nfs01 systemd[1]: Stopped Command Scheduler.
    May 03 20:33:26 nfs01 systemd[1]: Started Command Scheduler.
    May 03 20:33:26 nfs01 crond[1490]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 41% if used.)
    May 03 20:33:26 nfs01 crond[1490]: (CRON) INFO (running with inotify support)
    May 03 20:33:26 nfs01 crond[1490]: (CRON) INFO (@reboot jobs will be run at computer's startup.)
    May 04 13:00:33 nfs01 systemd[1]: Stopping Command Scheduler...
    May 04 13:00:33 nfs01 systemd[1]: Stopped Command Scheduler.non-zero return code
    172.16.1.41 | FAILED | rc=3 >>
    ● crond.service - Command Scheduler
       Loaded: loaded (/usr/lib/systemd/system/crond.service; disabled; vendor preset: enabled)
       Active: inactive (dead)
    
    May 03 20:32:03 backup crond[907]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 73% if used.)
    May 03 20:32:03 backup crond[907]: (CRON) INFO (running with inotify support)
    May 03 20:33:05 backup systemd[1]: Stopping Command Scheduler...
    May 03 20:33:05 backup systemd[1]: Stopped Command Scheduler.
    May 03 20:33:05 backup systemd[1]: Started Command Scheduler.
    May 03 20:33:05 backup crond[1473]: (CRON) INFO (RANDOM_DELAY will be scaled with factor 88% if used.)
    May 03 20:33:05 backup crond[1473]: (CRON) INFO (running with inotify support)
    May 03 20:33:05 backup crond[1473]: (CRON) INFO (@reboot jobs will be run at computer's startup.)
    May 04 10:15:50 backup systemd[1]: Stopping Command Scheduler...
    May 04 10:15:50 backup systemd[1]: Stopped Command Scheduler.non-zero return code
    

    3.1.10 cron 定时任务模块

    1. cron模块参数
    [root@m01 ~]# ansible-doc -s cron
    - name: Manage cron.d and crontab entries
      cron:
          backup:                # If set, create a backup of the crontab before it is modified. The location of the backup is returned
                                   in the `backup_file' variable by this module.
          cron_file:             # If specified, uses this file instead of an individual user's crontab. If this is a relative path, it
                                   is interpreted with respect to `/etc/cron.d'. If it is absolute, it
                                   will typically be `/etc/crontab'. Many linux distros expect (and some
                                   require) the filename portion to consist solely of upper- and lower-
                                   case letters, digits, underscores, and hyphens. To use the `cron_file'
                                   parameter you must specify the `user' as well.
          day:                   # Day of the month the job should run ( 1-31, *, */2, etc )
          disabled:              # If the job should be disabled (commented out) in the crontab. Only has effect if `state=present'.
          env:                   # If set, manages a crontab's environment variable. New variables are added on top of crontab. `name'
                                   and `value' parameters are the name and the value of environment
                                   variable.
          hour:                  # Hour when the job should run ( 0-23, *, */2, etc )
          insertafter:           # Used with `state=present' and `env'. If specified, the environment variable will be inserted after
                                   the declaration of specified environment variable.
          insertbefore:          # Used with `state=present' and `env'. If specified, the environment variable will be inserted before
                                   the declaration of specified environment variable.
          job:                   # The command to execute or, if env is set, the value of environment variable. The command should not
                                   contain line breaks. Required if `state=present'.
          minute:                # Minute when the job should run ( 0-59, *, */2, etc )
          month:                 # Month of the year the job should run ( 1-12, *, */2, etc )
          name:                  # Description of a crontab entry or, if env is set, the name of environment variable. Required if
                                   `state=absent'. Note that if name is not set and `state=present', then
                                   a new crontab entry will always be created, regardless of existing
                                   ones. This parameter will always be required in future releases.
          reboot:                # If the job should be run at reboot. This option is deprecated. Users should use special_time.
          special_time:          # Special time specification nickname.
          state:                 # Whether to ensure the job or environment variable is present or absent.
          user:                  # The specific user whose crontab should be modified. When unset, this parameter defaults to using
                                   `root'.
          weekday:               # Day of the week that the job should run ( 0-6 for Sunday-Saturday, *, etc )
    
    1. 实战
    [root@m01 ~]# ansible oldboy -m cron -a "name='sync time' minute=00 hour=00 job='/usr/bin/ntpdate ntp1.aliyun.com &>/dev/null'"
    172.16.1.41 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "envs": [], 
        "jobs": [
            "sync time"
        ]
    }
    172.16.1.31 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "envs": [], 
        "jobs": [
            "sync time"
        ]
    }
    
    [root@m01 ~]# ansible oldboy -m command -a "crontab -l"
    172.16.1.31 | CHANGED | rc=0 >>
    #time update
    */5 * * * * /usr/sbin/ntpdate ntp3.aliyun.com >/dev/null 2>&1
    #Ansible: sync time
    00 00 * * * /usr/bin/ntpdate ntp1.aliyun.com &>/dev/null
    172.16.1.41 | CHANGED | rc=0 >>
    #time ntpdate 
    */5 * * * *  ntpdate ntp3.aliyun.com >/dev/null 2>&1
    #rsync back check
    00 23 * * *   /bin/bash /server/scripts/back.sh &>/dev/null
    
    #Ansible: sync time
    00 00 * * * /usr/bin/ntpdate ntp1.aliyun.com &>/dev/null
    

    3.删除定时任务

    [root@m01 ~]# ansible oldboy -m cron -a "name='sync time' state=absent"
    172.16.1.41 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "envs": [], 
        "jobs": []
    }
    172.16.1.31 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "envs": [], 
        "jobs": []
    }
    [root@m01 ~]# ansible oldboy -m command -a "crontab -l"
    172.16.1.41 | CHANGED | rc=0 >>
    #time ntpdate 
    */5 * * * *  ntpdate ntp3.aliyun.com >/dev/null 2>&1
    #rsync back check
    00 23 * * *   /bin/bash /server/scripts/back.sh &>/dev/null
    172.16.1.31 | CHANGED | rc=0 >>
    #time update
    */5 * * * * /usr/sbin/ntpdate ntp3.aliyun.com >/dev/null 2>&1
    
    1. 实战
    [root@m01 ~]# ansible oldboy -m cron -a "name='backup sh' minute=05 hour=03 job='/bin/sh /server/scripts/backup.sh >/dev/null 2>&1'" 
    172.16.1.31 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "envs": [], 
        "jobs": [
            "backup sh"
        ]
    }
    172.16.1.41 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "envs": [], 
        "jobs": [
            "backup sh"
        ]
    }
    [root@m01 ~]# ansible oldboy -m shell -a "crontab -l" 
    172.16.1.41 | CHANGED | rc=0 >>
    #time ntpdate 
    */5 * * * *  ntpdate ntp3.aliyun.com >/dev/null 2>&1
    #rsync back check
    00 23 * * *   /bin/bash /server/scripts/back.sh &>/dev/null
    #Ansible: backup sh
    05 03 * * * /bin/sh /server/scripts/backup.sh >/dev/null 2>&1
    172.16.1.31 | CHANGED | rc=0 >>
    #time update
    */5 * * * * /bin/sh /usr/sbin/ntpdate ntp3.aliyun.com >/dev/null 2>&1
    #Ansible: backup sh
    05 03 * * * /server/scripts/backup.sh >/dev/null 2>&1
    

    5.注释定时任务

    [root@m01 ~]# ansible oldboy -m cron -a "name='backup sh' minute=05 hour=03 job='/bin/sh /server/scripts/backup.sh >/dev/null 2>&1' disabled=yes" 
    172.16.1.31 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "envs": [], 
        "jobs": [
            "backup sh"
        ]
    }
    172.16.1.41 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "envs": [], 
        "jobs": [
            "backup sh"
        ]
    }
    [root@m01 ~]# ansible oldboy -m shell -a "crontab -l" 
    172.16.1.41 | CHANGED | rc=0 >>
    #time ntpdate 
    */5 * * * *  ntpdate ntp3.aliyun.com >/dev/null 2>&1
    #rsync back check
    00 23 * * *   /bin/bash /server/scripts/back.sh &>/dev/null
    #Ansible: backup sh
    #05 03 * * * /bin/sh /server/scripts/backup.sh >/dev/null 2>&1
    172.16.1.31 | CHANGED | rc=0 >>
    #time update
    */5 * * * * /usr/sbin/ntpdate ntp3.aliyun.com >/dev/null 2>&1
    #Ansible: backup sh
    #05 03 * * * /bin/sh /server/scripts/backup.sh >/dev/null 2>&1
    

    扩展mount模块

    [root@m01 ~]# ansible oldboy -m mount -a "src=/dev/sr0 path=/mnt fstype=iso9660 state=mounted"
    172.16.1.41 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "dump": "0", 
        "fstab": "/etc/fstab", 
        "fstype": "iso9660", 
        "name": "/mnt", 
        "opts": "defaults", 
        "passno": "0", 
        "src": "/dev/sr0"
    }
    172.16.1.31 | CHANGED => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": true, 
        "dump": "0", 
        "fstab": "/etc/fstab", 
        "fstype": "iso9660", 
        "name": "/mnt", 
        "opts": "defaults", 
        "passno": "0", 
        "src": "/dev/sr0"
    }
    [root@m01 ~]# ansible oldboy -m shell -a "cat /etc/fstab"
    172.16.1.41 | CHANGED | rc=0 >>
    
    #
    # /etc/fstab
    # Created by anaconda on Thu Mar 26 22:35:42 2020
    #
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    #
    /dev/mapper/centos_node-root /                       xfs     defaults        0 0
    UUID=c436d5ae-9e2b-4212-b5d8-5028b8920ebe /boot                   xfs     defaults        0 0
    /dev/mapper/centos_node-swap swap                    swap    defaults        0 0
    /dev/sr0 /mnt iso9660 defaults 0 0
    172.16.1.31 | CHANGED | rc=0 >>
    
    #
    # /etc/fstab
    # Created by anaconda on Thu Mar 26 22:35:42 2020
    #
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    #
    /dev/mapper/centos_node-root /                       xfs     defaults        0 0
    UUID=c436d5ae-9e2b-4212-b5d8-5028b8920ebe /boot                   xfs     defaults        0 0
    /dev/mapper/centos_node-swap swap                    swap    defaults        0 0
    /dev/sr0 /mnt iso9660 defaults 0 0
    [root@m01 ~]# ansible oldboy -m shell -a "df -h"
    172.16.1.41 | CHANGED | rc=0 >>
    Filesystem                    Size  Used Avail Use% Mounted on
    devtmpfs                      979M     0  979M   0% /dev
    tmpfs                         991M     0  991M   0% /dev/shm
    tmpfs                         991M  9.5M  981M   1% /run
    tmpfs                         991M     0  991M   0% /sys/fs/cgroup
    /dev/mapper/centos_node-root   19G  2.1G   17G  12% /
    /dev/sda1                     497M  156M  342M  32% /boot
    tmpfs                         199M     0  199M   0% /run/user/0
    /dev/sr0                      4.3G  4.3G     0 100% /mnt
    172.16.1.31 | CHANGED | rc=0 >>
    Filesystem                    Size  Used Avail Use% Mounted on
    devtmpfs                      979M     0  979M   0% /dev
    tmpfs                         991M     0  991M   0% /dev/shm
    tmpfs                         991M  9.5M  981M   1% /run
    tmpfs                         991M     0  991M   0% /sys/fs/cgroup
    /dev/mapper/centos_node-root   19G  2.1G   17G  12% /
    /dev/sda1                     497M  156M  342M  32% /boot
    tmpfs                         199M     0  199M   0% /run/user/0
    /dev/sr0                      4.3G  4.3G     0 100% /mnt
    

    取消挂载

    [root@m01 ~]# ansible oldboy -m mount -a "src=/dev/sr0  path=/mnt/ fstype=iso9660 state=absent"
    172.16.1.41 | FAILED! => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "msg": "Error rmdir /mnt/: [Errno 39] Directory not empty: '/mnt/'"
    }
    172.16.1.31 | FAILED! => {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "msg": "Error rmdir /mnt/: [Errno 39] Directory not empty: '/mnt/'"
    }
    [root@m01 ~]# ansible oldboy -m shell -a "cat /etc/fstab"
    172.16.1.31 | CHANGED | rc=0 >>
    
    #
    # /etc/fstab
    # Created by anaconda on Thu Mar 26 22:35:42 2020
    #
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    #
    /dev/mapper/centos_node-root /                       xfs     defaults        0 0
    UUID=c436d5ae-9e2b-4212-b5d8-5028b8920ebe /boot                   xfs     defaults        0 0
    /dev/mapper/centos_node-swap swap                    swap    defaults        0 0
    172.16.1.41 | CHANGED | rc=0 >>
    
    #
    # /etc/fstab
    # Created by anaconda on Thu Mar 26 22:35:42 2020
    #
    # Accessible filesystems, by reference, are maintained under '/dev/disk'
    # See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
    #
    /dev/mapper/centos_node-root /                       xfs     defaults        0 0
    UUID=c436d5ae-9e2b-4212-b5d8-5028b8920ebe /boot                   xfs     defaults        0 0
    /dev/mapper/centos_node-swap swap                    swap    default
    #会报错,但是确实是卸载了
    

    四、ansible playbook剧本编写

    4.1.1 什么是playbook

    1. 把所有操作按照ansible编程语法格式,放在文件里执行就是playbook

    2.ansible playbook编写格式说明
    nsible剧本遵循PYyaml语法规则进行编写,yaml文件基本编写规则如下说明:

    规则一:缩进
    yaml使用一个固定的缩进风格表示数据层结构关系,需要每个缩进级别由两个空格组成。切记一定不能使用tab键进行缩进。

    规则二:冒号
    每个冒号后面一定要有一个空格(以冒号结尾不需要空格,表示文件路径的模版可以不需要空格)

    规则三:短横线
    想要表示列表项,使用一个短横杠加一个空格。多个项使用同样的缩进级别作为同一个列表的一部分

    4.1.2 playbook 编写实战

    1. 查询一个模块在playbook剧本中的使用方法
    [root@m01 /etc/ansible/yaml]# ansible-doc shell
    > SHELL    (/usr/lib/python2.7/site-packages/ansible/modules/commands/shell.py)
    ......
    EXAMPLES:
    
    - name: Execute the command in remote shell; stdout goes to the specified file on the remote.
      shell: somescript.sh >> somelog.txt
    
    - name: Change the working directory to somedir/ before executing the command.
      shell: somescript.sh >> somelog.txt
      args:
        chdir: somedir/
    
    # You can also use the 'args' form to provide the options.
    - name: This command will change the working directory to somedir/ and will only run when somedir/somelog.txt doesn't exist.
      shell: somescript.sh >> somelog.txt
      args:
        chdir: somedir/
        creates: somelog.txt
    
    # You can also use the 'cmd' parameter instead of free form format.
    - name: This command will change the working directory to somedir/.
      shell:
        cmd: ls -l | grep log
        chdir: somedir/
    
    - name: Run a command that uses non-posix shell-isms (in this example /bin/sh doesn't handle redirection and wildcards together but b
      shell: cat < /tmp/*txt
      args:
        executable: /bin/bash
    
    - name: Run a command using a templated variable (always use quote filter to avoid injection)
      shell: cat {{ myfile|quote }}
    
    1. 创建playbook剧本存放目录
    [root@m01 ~]# mkdir -p  /etc/ansible/yaml/
    [root@m01 ~]# ll -ld /etc/ansible/yaml/
    drwxr-xr-x 2 root root 6 May  5 09:26 /etc/ansible/yaml/
    
    1. playbook 编写实战
    [root@m01 /etc/ansible/yaml]# ansible-doc shell
    [root@m01 ~]# cat /etc/ansible/yaml/ceshi.yml
    - hosts: oldboy
      tasks:
        - name: create log.txt file
          shell: echo 'I am study linux' >/tmp/linux.log
    #检查语法是否正确加-C
    [root@m01 ~]# ansible-playbook -C /etc/ansible/yaml/ceshi.yml 
    
    PLAY [oldboy] ***********************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.41]
    ok: [172.16.1.31]
    
    TASK [create log.txt file] **********************************************************************************************************
    skipping: [172.16.1.31]
    skipping: [172.16.1.41]
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.31                : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    172.16.1.41                : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    
    #没有报错去掉-C,表示正式执行
    [root@m01 ~]# ansible-playbook /etc/ansible/yaml/ceshi.yml 
    
    PLAY [oldboy] ***********************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.31]
    ok: [172.16.1.41]
    
    TASK [create log.txt file] **********************************************************************************************************
    changed: [172.16.1.31]
    changed: [172.16.1.41]
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.31                : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.41                : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    1. 检查是否成功
    [root@m01 ~]# ansible oldboy -m shell -a "cat /tmp/linux.log"
    172.16.1.41 | CHANGED | rc=0 >>
    I am study linux
    172.16.1.31 | CHANGED | rc=0 >>
    I am study linux
    
    1. playbook 添加定时任务
    [root@m01 /etc/ansible/yaml]# cat ./cron.yml 
    - hosts: oldboy
      tasks:
        - name: create crontab
          cron: name='stady linux' minute=30 hour=8  job='/bin/sh /server/scripts/class.sh >/dev/null 2>&1'
    [root@m01 /etc/ansible/yaml]# ansible-playbook -C ./cron.yml 
    
    PLAY [oldboy] ***********************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.41]
    ok: [172.16.1.31]
    
    TASK [create crontab] ***************************************************************************************************************
    changed: [172.16.1.31]
    changed: [172.16.1.41]
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.31                : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.41                : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    [root@m01 /etc/ansible/yaml]# ansible-playbook  ./cron.yml 
    
    PLAY [oldboy] ***********************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.31]
    ok: [172.16.1.41]
    
    TASK [create crontab] ***************************************************************************************************************
    changed: [172.16.1.41]
    changed: [172.16.1.31]
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.31                : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.41                : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    [root@m01 /etc/ansible/yaml]# ansible oldboy -m shell -a "crontab -l"
    172.16.1.41 | CHANGED | rc=0 >>
    #time ntpdate 
    */5 * * * *  ntpdate ntp3.aliyun.com >/dev/null 2>&1
    #rsync back check
    00 23 * * *   /bin/bash /server/scripts/back.sh &>/dev/null
    #Ansible: backup sh
    #05 03 * * * /bin/sh /server/scripts/backup.sh >/dev/null 2>&1
    #Ansible: stady linux
    30 8 * * * /bin/sh /server/scripts/class.sh >/dev/null 2>&1
    172.16.1.31 | CHANGED | rc=0 >>
    #time update
    */5 * * * * /usr/sbin/ntpdate ntp3.aliyun.com >/dev/null 2>&1
    #Ansible: backup sh
    #05 03 * * * /bin/sh /server/scripts/backup.sh >/dev/null 2>&1
    #Ansible: stady linux
    30 8 * * * /bin/sh /server/scripts/class.sh >/dev/null 2>&1
    

    五、 playbook的扩展写法格式

    5.1.1 playbook的重要

    1. playbook的重要功能介绍
        a 在剧本中设置变量信息  OK 3种方式 常用方式--剧本中设置
    	b 在剧本中设置注册信息  OK 执行剧本时,可以显示输出命令结果信息  debug
    	b 在剧本中设置判断信息  OK                                       setup
    	c 在剧本中设置循环信息  OK
    	d 在剧本中设置错误忽略  OK
    	d 在剧本中设置标签信息  OK
    	e 在剧本中设置触发信息  OK
    	详细的剧本扩展:
    	https://docs.ansible.com/ansible/latest/user_guide/playbooks.html
    

    5.1.2 playbook vars(变量)的使用

    1. 定义和使用变量
    [root@m01 /etc/ansible/yaml]# vim ./rsync.yaml 
    - hosts: 172.16.1.151
      vars:      #设置变量
        backupdir: /backup  #定义变量信息
        passfile: rsync.password   #定义变量信息
      tasks:
        - name: install rsync
          yum: name=rsync state=installed
        - name: copy config
          copy: src=/etc/rsyncd.conf dest=/etc/
        - name: useradd rsync
          user: name=rsync create_home=no shell=/sbin/nologin
        - name: create backup file
          file: path={{ backupdir }} #在yaml语法里,{{ }}是用来解析变量的,相当于shell里的$  state=directory #在yaml语法里,{{ }}是用来解析变量的,相当于shell里的$ owner=rsync group=rsync
        - name: create password
          copy: content='rsync_backup:oldboy' dest=/etc/{{ passfile }} #在yaml语法里,{{ }}是用来解析变量的,相当于shell里的$ mode=600
        - name: system rsyncd
          systemd: name=rsyncd.service state=started enabled=yes
    
    1. 测试结果
    [root@m01 /etc/ansible/yaml]# ansible-playbook -C ./rsync.yaml 
    
    PLAY [172.16.1.151] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [copy config] ******************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [useradd rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create backup file] ***********************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create password] **************************************************************************************************************
    ok: [172.16.1.151]
    
      SK [system rsyncd] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    PLAY [172.16.1.8] *******************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.8]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.8]
    
    TASK [create password file] *********************************************************************************************************
    ok: [172.16.1.8]
    
    TASK [check test backup] ************************************************************************************************************
    skipping: [172.16.1.8]
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.151               : ok=7    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.8                 : ok=3    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    #完全ok
    

    5.1.3 在剧本中设置register(注册)信息

    1. 设置register(注册)信息
    [root@m01 /etc/ansible/yaml]# vim  ./rsync.yaml 
    - hosts: 172.16.1.151
      vars:
        backupdir: /backup
        passfile: rsync.password
      tasks:
        - name: install rsync
          yum: name=rsync state=installed
        - name: copy config
          copy: src=/etc/rsyncd.conf dest=/etc/
        - name: useradd rsync
          user: name=rsync create_home=no shell=/sbin/nologin
        - name: create backup file
          file: path={{ backupdir }} state=directory owner=rsync group=rsync
        - name: create password
          copy: content='rsync_backup:oldboy' dest=/etc/{{ passfile }} mode=600
        - name: system rsyncd
          systemd: name=rsyncd.service state=started enabled=yes
        - name: check port
          shell: netstat -luntp|grep 873
          register: get_server_port
        - name: display port info
          debug: msg={{ get_server_port.stdout_lines }}
    
    1. 测试结果
    [root@m01 /etc/ansible/yaml]# ansible-playbook   ./rsync.yaml 
    
    PLAY [172.16.1.151] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [copy config] ******************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [useradd rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create backup file] ***********************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create password] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [system rsyncd] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [check port] *******************************************************************************************************************
    changed: [172.16.1.151]
    
    TASK [display port info] ************************************************************************************************************
    ok: [172.16.1.151] => {
        "msg": [
            "tcp        0      0 0.0.0.0:873             0.0.0.0:*               LISTEN      15722/rsync         ", 
            "tcp6       0      0 :::873                  :::*                    LISTEN      15722/rsync         "
        ]
    }
    
    PLAY [172.16.1.8] *******************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.8]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.8]
    
    TASK [create password file] *********************************************************************************************************
    ok: [172.16.1.8]
    
    TASK [check test backup] ************************************************************************************************************
    changed: [172.16.1.8]
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.151               : ok=9    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.8                 : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    

    5.1.4 设置判断(when)信息

    1. 如何设置判断(when)信息
    [root@m01 /etc/ansible/yaml]# vim +32 ./rsync.yaml 
        - name: useradd rsync
          user: name=rsync create_home=no shell=/sbin/nologin
        - name: create backup file
          file: path={{ backupdir }} state=directory owner=rsync group=rsync
        - name: create password
          copy: content='rsync_backup:oldboy' dest=/etc/{{ passfile }} mode=600
        - name: system rsyncd
          systemd: name=rsyncd.service state=started enabled=yes
        - name: check port
          shell: netstat -luntp|grep 873
          register: get_server_port
        - name: display port info
          debug: msg={{ get_server_port.stdout_lines }}
    
    
    - hosts: rsync_client
      vars:
        passfile: rsync.password
      tasks:
        - name: install rsync
          yum: name=rsync state=installed
        - name: create password file
          copy: content=oldboy dest=/etc/{{ passfile }} mode=600
        - name: create web01
          file: dest=/tmp/test_web01.txt state=touch
          when: (ansible_hostname == "web01")  #如果主机名是web01,就执行上一条命令,否则就跳过(不执行上一条命令
        - name: create web02
          file: dest=/tmp/test_web02.txt state=touch
          when: (ansible_hostname == "web02")  #如果主机名是web02,就执行上一条命令,否则就跳过(不执行上一条命令
        - name : check test backup
          shell: rsync -avz /tmp/test_web01.txt rsync_backup@172.16.1.151::backup --password-file=/etc/{{ passfile }}
          when: (ansible_hostname == "web01")  #如果主机名是web01,就执行上一条命令,否则就跳过(不执行上一条命令
           - name : check test bata
          shell: rsync -avz /tmp/test_web02.txt rsync_backup@172.16.1.151::data --password-file=/etc/{{ passfile }}
          when: (ansible_hostname == "web02")  #如果主机名是web02,就执行上一条命令,否则就跳过(不执行上一条命令)
          
    
    1. 测试
    [root@m01 /etc/ansible/yaml]# ansible-playbook ./rsync.yaml 
    
    PLAY [172.16.1.151] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [copy config] ******************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [useradd rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create backup file] ***********************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create password] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [system rsyncd] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [check port] *******************************************************************************************************************
    changed: [172.16.1.151]
    
    TASK [display port info] ************************************************************************************************************
    ok: [172.16.1.151] => {
        "msg": [
            "tcp        0      0 0.0.0.0:873             0.0.0.0:*               LISTEN      15722/rsync         ", 
            "tcp6       0      0 :::873                  :::*                    LISTEN      15722/rsync         "
        ]
    }
    
    PLAY [rsync_client] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.8]
    ok: [172.16.1.7]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [create password file] *********************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [create web01] *****************************************************************************************************************
    skipping: [172.16.1.8]
    changed: [172.16.1.7]
    
    TASK [create web02] *****************************************************************************************************************
    skipping: [172.16.1.7]
    changed: [172.16.1.8]
    
    TASK [check test backup] ************************************************************************************************************
    skipping: [172.16.1.8]
    changed: [172.16.1.7]
    
    TASK [check test bata] **************************************************************************************************************
    skipping: [172.16.1.7]
    changed: [172.16.1.8]
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.151               : ok=9    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.7                 : ok=5    changed=2    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0   
    172.16.1.8                 : ok=5    changed=2    unreachable=0    failed=0    skipped=2    rescued=0    ignored=0   
    
    1. 获取内置变量的方法
    [root@m01 /etc/ansible/yaml]# ansible rsync_client -m setup 
    172.16.1.8 | SUCCESS => {
        "ansible_facts": {
            "ansible_all_ipv4_addresses": [
                "172.16.1.8", 
                "10.0.0.8"
            ], 
            "ansible_all_ipv6_addresses": [
                "fe80::20c:29ff:feba:a21b", 
                "fe80::20c:29ff:feba:a211"
            ], 
            "ansible_apparmor": {
                "status": "disabled"
            }, 
            "ansible_architecture": "x86_64", 
            "ansible_bios_date": "07/29/2019", 
            "ansible_bios_version": "6.00", 
            "ansible_cmdline": {
                "BOOT_IMAGE": "/vmlinuz-3.10.0-1062.18.1.el7.x86_64", 
                "LANG": "en_US.UTF-8", 
                "biosdevname": "0", 
                "net.ifnames": "0", 
    
    1. 指定需要的内置变量
    [root@m01 /etc/ansible/yaml]# ansible rsync_client -m setup -a "filter=ansible_hostname"
    172.16.1.7 | SUCCESS => {
        "ansible_facts": {
            "ansible_hostname": "web01", 
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false
    }
    172.16.1.8 | SUCCESS => {
        "ansible_facts": {
            "ansible_hostname": "web02", 
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false
    }
    
    1. 常用的内置变量
      常见主机信息:
        ansible_all_ipv4_addresses:				仅显示ipv4的信息。
        ansible_devices:							仅显示磁盘设备信息。
        ansible_distribution:						显示是什么系统,例:centos,suse等。
        ansible_distribution_major_version:		显示是系统主版本。
        ansible_distribution_version:				仅显示系统版本。
        ansible_machine:							显示系统类型,例:32位,还是64位。
        ansible_eth0:								仅显示eth0的信息。
        ansible_hostname:							仅显示主机名。
        ansible_kernel:							仅显示内核版本。
        ansible_lvm:								显示lvm相关信息。
        ansible_memtotal_mb:						显示系统总内存。
        ansible_memfree_mb:						显示可用系统内存。
        ansible_memory_mb:							详细显示内存情况。
        ansible_swaptotal_mb:						显示总的swap内存。
        ansible_swapfree_mb:						显示swap内存的可用内存。
        ansible_mounts:							显示系统磁盘挂载情况。
        ansible_processor:							显示cpu个数(具体显示每个cpu的型号)。
        ansible_processor_vcpus:					显示cpu个数(只显示总的个数)。
    

    5.1.5 playbook 设置循(with_items)环信息

    1. 如何在playbook中设置循环(with_items)信息
    
    [root@m01 /etc/ansible/yaml]# vim ./rsync.yaml 
        - name: check port
          shell: netstat -luntp|grep 873
          register: get_server_port
    - hosts: 172.16.1.151
      vars:
        backupdir: /backup
        conffile: rsyncd.conf
        passfile: rsync.password
      tasks:
        - name: install rsync
          yum: name=rsync state=installed
        - name: push copy config & password
          copy: src=/etc/{{ item.src }} dest=/etc/{{ item.dest }} mode={{ item.mode }} #设置循环
          with_items:
            - { src: '{{ conffile }}', dest: '{{ conffile }}', mode: 644 }  #设置循环信息
            - { src: '{{ passfile }}', dest: '{{ passfile }}', mode: 600 }  #设置循环信息
        - name: useradd rsync
          user: name=rsync create_home=no shell=/sbin/nologin
        - name: create backup file
          file: path={{ backupdir }} state=directory owner=rsync group=rsync
        - name: system rsyncd
          systemd: name=rsyncd.service state=started enabled=yes
        - name: check port
          shell: netstat -luntp|grep 873
          register: get_server_port
        - name: display port info
          debug: msg={{ get_server_port.stdout_lines }}
    
    
    - hosts: rsync_client
      vars:
        passfile: rsync.password
      tasks:
        - name: install rsync
          yum: name=rsync state=installed
        - name: create password file
          copy: content=oldboy dest=/etc/{{ passfile }} mode=600
        - name: create web01 file & create web01 file
          file: dest=/tmp/{{ item.dest }} state={{ item.state }} #设置循环
          with_items:
            - { dest: test_web01.txt, state: touch }   #设置循环信息
            - { dest: test_web02.txt, state: touch }   #设置循环信息
        - name : check test backup & check test data
          shell: rsync -avz /tmp/test_web01.txt rsync_backup@172.16.1.151::backup --password-file=/etc/{{ passfile }}
          when: (ansible_hostname == "web01")
        - name : check test bata
          shell: rsync -avz /tmp/test_web02.txt rsync_backup@172.16.1.151::data --password-file=/etc/{{ passfile }}
          when: (ansible_hostname == "web02")
    
    
    1. 测试
    [root@m01 /etc/ansible/yaml]# ansible-playbook ./rsync.yaml 
    
    PLAY [172.16.1.151] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [push copy config & password] **************************************************************************************************
    ok: [172.16.1.151] => (item={u'dest': u'rsyncd.conf', u'src': u'rsyncd.conf', u'mode': 644})
    ok: [172.16.1.151] => (item={u'dest': u'rsync.password', u'src': u'rsync.password', u'mode': 600})
    
    TASK [useradd rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create backup file] ***********************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [system rsyncd] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [check port] *******************************************************************************************************************
    changed: [172.16.1.151]
    
    TASK [display port info] ************************************************************************************************************
    ok: [172.16.1.151] => {
        "msg": [
            "tcp        0      0 0.0.0.0:873             0.0.0.0:*               LISTEN      15722/rsync         ", 
            "tcp6       0      0 :::873                  :::*                    LISTEN      15722/rsync         "
        ]
    }
    
    PLAY [rsync_client] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.8]
    ok: [172.16.1.7]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [create password file] *********************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [create web01 file & create web01 file] ****************************************************************************************
    changed: [172.16.1.7] => (item={u'dest': u'test_web01.txt', u'state': u'touch'})
    changed: [172.16.1.8] => (item={u'dest': u'test_web01.txt', u'state': u'touch'})
    changed: [172.16.1.7] => (item={u'dest': u'test_web02.txt', u'state': u'touch'})
    changed: [172.16.1.8] => (item={u'dest': u'test_web02.txt', u'state': u'touch'})
    
    TASK [check test backup & check test data] ******************************************************************************************
    skipping: [172.16.1.8]
    changed: [172.16.1.7]
    
    TASK [check test bata] **************************************************************************************************************
    skipping: [172.16.1.7]
    changed: [172.16.1.8]
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.151               : ok=8    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.7                 : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    172.16.1.8                 : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    
    

    5.1.6 playbook 设置错误忽略(ignore_rrorrs)

    1. playbook中设置错误忽略(ignore_rrorrs)
    - hosts: 172.16.1.151
      vars:
        backupdir: /backup
        databakdir: /data
        conffile: rsyncd.conf
        passfile: rsync.password
      tasks:
        - name: install rsync
          yum: name=rsync state=installed
        - name: push copy config & password
          copy: src=/etc/{{ item.src }} dest=/etc/{{ item.dest }} mode={{ item.mode }}
          with_items:
            - { src: '{{ conffile }}', dest: '{{ conffile }}', mode: 644 }
            - { src: '{{ passfile }}', dest: '{{ passfile }}', mode: 600 }
        - name: useradd rsync
          user: name=rsync create_home=no shell=/sbin/nologin
        - name: create backup file & create backup file
          file: pth={{ item.path }} state={{ item.state }} owner={{ item.owner }} group={{ item.group }}
          with_items:
            - { path: '{{ backupdir }}', state: directory, owner: rsync, group: rsync }
            - { path: '{{ databakdir }}', state: directory, owner: rsync, group: rsync }
          ignore_errors: yes
        - name: system rsyncd
          systemd: name=rsyncd.service state=started enabled=yes
        - name: check port
          shell: netstat -luntp|grep 873
          register: get_server_port
    - hosts: 172.16.1.151
      vars:
        backupdir: /backup
        databakdir: /data
        conffile: rsyncd.conf
        passfile: rsync.password
      tasks:
        - name: install rsync
          yum: name=rsync state=installed
        - name: push copy config & password
          copy: src=/etc/{{ item.src }} dest=/etc/{{ item.dest }} mode={{ item.mode }}
          with_items:
            - { src: '{{ conffile }}', dest: '{{ conffile }}', mode: 644 }
            - { src: '{{ passfile }}', dest: '{{ passfile }}', mode: 600 }
        - name: useradd rsync
          user: name=rsync create_home=no shell=/sbin/nologin
        - name: create backup file & create backup file
          file: pth={{ item.path }} state={{ item.state }} owner={{ item.owner }} group={{ item.group }}
          with_items:
            - { path: '{{ backupdir }}', state: directory, owner: rsync, group: rsync }
            - { path: '{{ databakdir }}', state: directory, owner: rsync, group: rsync }
          ignore_errors: yes  #设置忽略错误,往下执行命令
        - name: system rsyncd
          systemd: name=rsyncd.service state=started enabled=yes
        - name: check port
          shell: netstat -luntp|grep 873
          register: get_server_port
        - name: display port info
          debug: msg={{ get_server_port.stdout_lines }}
    
    
    - hosts: rsync_client
      vars:
        passfile: rsync.password
      tasks:
        - name: install rsync
          yum: name=rsync state=installed
        - name: create password file
          copy: content=oldboy dest=/etc/{{ passfile }} mode=600
        - name: create web01 file & create web01 file
          file: dest=/tmp/{{ item.dest }} state={{ item.state }}
          with_items:
            - { dest: test_web01.txt, state: touch }
            - { dest: test_web02.txt, state: touch }
        - name : check test backup & check test data
          shell: rsync -avz /tmp/test_web01.txt rsync_backup@172.16.1.151::backup --password-file=/etc/{{ passfile }}
          when: (ansible_hostname == "web01")
        - name : check test bata
          shell: rsync -avz /tmp/test_web02.txt rsync_backup@172.16.1.151::data --password-file=/etc/{{ passfile }}
          when: (ansible_hostname == "web02")
    
    1. 测试
    [root@m01 /etc/ansible/yaml]# ansible-playbook  ./rsync.yaml 
    
    PLAY [172.16.1.151] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [push copy config & password] **************************************************************************************************
    ok: [172.16.1.151] => (item={u'dest': u'rsyncd.conf', u'src': u'rsyncd.conf', u'mode': 644})
    ok: [172.16.1.151] => (item={u'dest': u'rsync.password', u'src': u'rsync.password', u'mode': 600})
    
    TASK [useradd rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create backup file & create backup file] **************************************************************************************
    failed: [172.16.1.151] (item={u'owner': u'rsync', u'path': u'/backup', u'state': u'directory', u'group': u'rsync'}) => {"ansible_loop_var": "item", "changed": false, "item": {"group": "rsync", "owner": "rsync", "path": "/backup", "state": "directory"}, "msg": "Unsupported parameters for (file) module: pth Supported parameters include: _diff_peek, _original_basename, access_time, access_time_format, attributes, backup, content, delimiter, directory_mode, follow, force, group, mode, modification_time, modification_time_format, owner, path, recurse, regexp, remote_src, selevel, serole, setype, seuser, src, state, unsafe_writes"}
    failed: [172.16.1.151] (item={u'owner': u'rsync', u'path': u'/data', u'state': u'directory', u'group': u'rsync'}) => {"ansible_loop_var": "item", "changed": false, "item": {"group": "rsync", "owner": "rsync", "path": "/data", "state": "directory"}, "msg": "Unsupported parameters for (file) module: pth Supported parameters include: _diff_peek, _original_basename, access_time, access_time_format, attributes, backup, content, delimiter, directory_mode, follow, force, group, mode, modification_time, modification_time_format, owner, path, recurse, regexp, remote_src, selevel, serole, setype, seuser, src, state, unsafe_writes"}
    ...ignoring    #已经忽略了错误往下执行命令
    
    TASK [system rsyncd] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [check port] *******************************************************************************************************************
    changed: [172.16.1.151]
    
    TASK [display port info] ************************************************************************************************************
    ok: [172.16.1.151] => {
        "msg": [
            "tcp        0      0 0.0.0.0:873             0.0.0.0:*               LISTEN      15722/rsync         ", 
            "tcp6       0      0 :::873                  :::*                    LISTEN      15722/rsync         "
        ]
    }
    
    PLAY [rsync_client] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [create password file] *********************************************************************************************************
    ok: [172.16.1.7]
      : [172.16.1.8]
    
    TASK [create web01 file & create web01 file] ****************************************************************************************
    changed: [172.16.1.7] => (item={u'dest': u'test_web01.txt', u'state': u'touch'})
    changed: [172.16.1.8] => (item={u'dest': u'test_web01.txt', u'state': u'touch'})
    changed: [172.16.1.7] => (item={u'dest': u'test_web02.txt', u'state': u'touch'})
    changed: [172.16.1.8] => (item={u'dest': u'test_web02.txt', u'state': u'touch'})
    
    TASK [check test backup & check test data] ******************************************************************************************
    skipping: [172.16.1.8]
    changed: [172.16.1.7]
    
    TASK [check test bata] **************************************************************************************************************
    skipping: [172.16.1.7]
    changed: [172.16.1.8]
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.151               : ok=8    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1   
    172.16.1.7                 : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    172.16.1.8                 : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0 
    

    5.1.7 playbook 添加标签(tags)

    1. 在playbook中添加标签(tags)
    [root@m01 /etc/ansible/yaml]# vim  ./rsync.yaml 
    - hosts: 172.16.1.151
      vars:
        backupdir: /backup
        databakdir: /data
        conffile: rsyncd.conf
        passfile: rsync.password
      tasks:
        - name: install rsync
          yum: name=rsync state=installed
        - name: push copy config & password
          copy: src=/etc/{{ item.src }} dest=/etc/{{ item.dest }} mode={{ item.mode }}
          with_items:
            - { src: '{{ conffile }}', dest: '{{ conffile }}', mode: 644 }
            - { src: '{{ passfile }}', dest: '{{ passfile }}', mode: 600 }
        - name: useradd rsync
          user: name=rsync create_home=no shell=/sbin/nologin
        - name: create backup file & create backup file
          file: path={{ item.path }} state={{ item.state }} owner={{ item.owner }} group={{ item.group }}
          with_items:
            - { path: '{{ backupdir }}', state: directory, owner: rsync, group: rsync }
            - { path: '{{ databakdir }}', state: directory, owner: rsync, group: rsync }
          tags: create file    #添加标签 ,在执行的时候结合参数可以执行或跳过添加标签的这个执行任务(上一条完整的命令)
        - name: system rsyncd
          systemd: name=rsyncd.service state=started enabled=yes
        - name: check port
          shell: netstat -luntp|grep 873
          register: get_server_port
        - name: display port info
          debug: msg={{ get_server_port.stdout_lines }}
    
    
    - hosts: rsync_client
      vars:
        passfile: rsync.password
      tasks:
        - name: install rsync
          yum: name=rsync state=installed
        - name: create password file
          copy: content=oldboy dest=/etc/{{ passfile }} mode=600
        - name: create web01 file & create web01 file
          file: dest=/tmp/{{ item.dest }} state={{ item.state }}
          with_items:
            - { dest: test_web01.txt, state: touch }
            - { dest: test_web02.txt, state: touch }
        - name : check test backup & check test data
          shell: rsync -avz /tmp/test_web01.txt rsync_backup@172.16.1.151::backup --password-file=/etc/{{ passfile }}
          when: (ansible_hostname == "web01")
        - name : check test bata
          shell: rsync -avz /tmp/test_web02.txt rsync_backup@172.16.1.151::data --password-file=/etc/{{ passfile }}
          when: (ansible_hostname == "web02")
    
    
    1. 测试 执行添加标签的这行命令 其它命令不执行
    [root@m01 /etc/ansible/yaml]# ansible-playbook --tags='create file' ./rsync.yaml 
    
    PLAY [172.16.1.151] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create backup file & create backup file] **************************************************************************************
    ok: [172.16.1.151] => (item={u'owner': u'rsync', u'path': u'/backup', u'state': u'directory', u'group': u'rsync'})
    ok: [172.16.1.151] => (item={u'owner': u'rsync', u'path': u'/data', u'state': u'directory', u'group': u'rsync'})
    
    PLAY [rsync_client] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.151               : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.7                 : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.8                 : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    [root@m01 /etc/ansible/yaml]# ansible-playbook -t='create file' ./rsync.yaml 
    
    PLAY [172.16.1.151] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create backup file & create backup file] **************************************************************************************
    ok: [172.16.1.151] => (item={u'owner': u'rsync', u'path': u'/backup', u'state': u'directory', u'group': u'rsync'})
    ok: [172.16.1.151] => (item={u'owner': u'rsync', u'path': u'/data', u'state': u'directory', u'group': u'rsync'})
    
    PLAY [rsync_client] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.8]
    ok: [172.16.1.7]
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.151               : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.7                 : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.8                 : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    
    
    1. 测试 跳过添加标签的这行命令,执行其它命令
    [root@m01 /etc/ansible/yaml]# ansible-playbook --skip-tags='create file' ./rsync.yaml 
    
    PLAY [172.16.1.151] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [push copy config & password] **************************************************************************************************
    ok: [172.16.1.151] => (item={u'dest': u'rsyncd.conf', u'src': u'rsyncd.conf', u'mode': 644})
    ok: [172.16.1.151] => (item={u'dest': u'rsync.password', u'src': u'rsync.password', u'mode': 600})
    
    TASK [useradd rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [system rsyncd] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [check port] *******************************************************************************************************************
    changed: [172.16.1.151]
    
    TASK [display port info] ************************************************************************************************************
    ok: [172.16.1.151] => {
        "msg": [
            "tcp        0      0 0.0.0.0:873             0.0.0.0:*               LISTEN      15722/rsync         ", 
            "tcp6       0      0 :::873                  :::*                    LISTEN      15722/rsync         "
        ]
    }
    
    PLAY [rsync_client] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.8]
    ok: [172.16.1.7]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [create password file] *********************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [create web01 file & create web01 file] ****************************************************************************************
    changed: [172.16.1.7] => (item={u'dest': u'test_web01.txt', u'state': u'touch'})
    changed: [172.16.1.8] => (item={u'dest': u'test_web01.txt', u'state': u'touch'})
    changed: [172.16.1.7] => (item={u'dest': u'test_web02.txt', u'state': u'touch'})
    changed: [172.16.1.8] => (item={u'dest': u'test_web02.txt', u'state': u'touch'})
    
    TASK [check test backup & check test data] ******************************************************************************************
    skipping: [172.16.1.8]
    changed: [172.16.1.7]
    
    TASK [check test bata] **************************************************************************************************************
    skipping: [172.16.1.7]
    changed: [172.16.1.8]
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.151               : ok=7    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.7                 : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    172.16.1.8                 : ok=5    changed=2    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    
    

    5.1.8 设置playbook 触发(notify)信息,接受触发(handlers)和tasks 平行

    1. 在playbook中设置触发(notify)信息
    [root@m01 /etc/ansible/yaml]# vim /etc/rsyncd.conf 
    #rsync_config
    #created by chenhj 2020-4-28
    uid = rsync
    gid = rsync
    port = 874   #端口发生改变
    fake super = yes
    use chroot = no
    max connections = 200
    timeout = 600
    pid file = /var/run/rsyncd.pid
    lock file = /var/run/rsync.lock
    log file = /var/log/rsyncd.log
    ignore errors
    read only = false
    list = false
    hosts allow = 172.16.1.0/24
    auth users = rsync_backup
    secrets file = /etc/rsync.password
    [backup]
    comment = welcome to oldboyedu backup!
    path = /backup/
    [data]
    path = /data/
    
    #在设置剧本中设置触发(notify)信息
    [root@m01 /etc/ansible/yaml]# vim  ./rsync.yaml
    - hosts: 172.16.1.151
      vars:
        backupdir: /backup
        databakdir: /data
        conffile: rsyncd.conf
        passfile: rsync.password
      tasks:
        - name: install rsync
          yum: name=rsync state=installed
        - name: push copy config & password
          copy: src=/etc/{{ item.src }} dest=/etc/{{ item.dest }} mode={{ item.mode }}
          with_items:
            - { src: '{{ conffile }}', dest: '{{ conffile }}', mode: 644 }
            - { src: '{{ passfile }}', dest: '{{ passfile }}', mode: 600 }
          notify: systemctl restart rsyncd  #如果上一条命令中的文件属性发生改变就开启触发,因为我改了rsyncd.conf文件里的端口,所以触发是有效的。
        - name: useradd rsync
          user: name=rsync create_home=no shell=/sbin/nologin
        - name: create backup file & create backup file
          file: path={{ item.path }} state={{ item.state }} owner={{ item.owner }} group={{ item.group }}
          with_items:
            - { path: '{{ backupdir }}', state: directory, owner: rsync, group: rsync }
            - { path: '{{ databakdir }}', state: directory, owner: rsync, group: rsync }
        - name: systemctl start rsyncd
          systemd: name=rsyncd.service state=started enabled=yes
        - name: check port
          shell: netstat -luntp|grep 873
          register: get_server_port
        - name: display port info
          debug: msg={{ get_server_port.stdout_lines }}
      handlers:          #有过上面设置的触发有效,这里就会接受触发并执行触发设置的命令
        - name: systemctl restart rsyncd
          systemd: name=rsyncd.service state=restarted enabled=yes
    
    - hosts: rsync_client
      vars:
        passfile: rsync.password
      tasks:
        - name: install rsync
          yum: name=rsync state=installed
        - name: create password file
          copy: content=oldboy dest=/etc/{{ passfile }} mode=600
        - name: create web01 file & create web01 file
          file: dest=/tmp/{{ item.dest }} state={{ item.state }}
          with_items:
            - { dest: test_web01.txt, state: touch }
            - { dest: test_web02.txt, state: touch }
        - name : check test backup & check test data
          shell: rsync -avz /tmp/test_web01.txt rsync_backup@172.16.1.151::backup --password-file=/etc/{{ passfile }}
          when: (ansible_hostname == "web01")
        - name : check test bata
          shell: rsync -avz /tmp/test_web02.txt rsync_backup@172.16.1.151::data --password-file=/etc/{{ passfile }}
          when: (ansible_hostname == "web02")
    
    
    1. 测试触发效果
    [root@m01 /etc/ansible/yaml]# ansible-playbook ./rsync.yaml 
    
    PLAY [172.16.1.151] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [push copy config & password] **************************************************************************************************
    changed: [172.16.1.151] => (item={u'dest': u'rsyncd.conf', u'src': u'rsyncd.conf', u'mode': 644})
    ok: [172.16.1.151] => (item={u'dest': u'rsync.password', u'src': u'rsync.password', u'mode': 600})
    
    TASK [useradd rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create backup file & create backup file] **************************************************************************************
    ok: [172.16.1.151] => (item={u'owner': u'rsync', u'path': u'/backup', u'state': u'directory', u'group': u'rsync'})
    ok: [172.16.1.151] => (item={u'owner': u'rsync', u'path': u'/data', u'state': u'directory', u'group': u'rsync'})
    
    TASK [systemctl start rsyncd] *******************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [check port] *******************************************************************************************************************
    changed: [172.16.1.151]
    
    TASK [display port info] ************************************************************************************************************
    ok: [172.16.1.151] => {
        "msg": [
            "tcp        0      0 0.0.0.0:873             0.0.0.0:*               LISTEN      15722/rsync         ", 
            "tcp6       0      0 :::873                  :::*                    LISTEN      15722/rsync         "
        ]
    }
    
    RUNNING HANDLER [systemctl restart rsyncd]  #激活了触发器,重启的服务。 ******************************************************************************************
    changed: [172.16.1.151]
    
    PLAY [rsync_client] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.8]
    ok: [172.16.1.7]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [create password file] *********************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [create web01 file & create web01 file] ****************************************************************************************
    changed: [172.16.1.7] => (item={u'dest': u'test_web01.txt', u'state': u'touch'})
    changed: [172.16.1.8] => (item={u'dest': u'test_web01.txt', u'state': u'touch'})
    changed: [172.16.1.7] => (item={u'dest': u'test_web02.txt', u'state': u'touch'})
    changed: [172.16.1.8] => (item={u'dest': u'test_web02.txt', u'state': u'touch'})
    
    TASK [check test backup & check test data] ******************************************************************************************
      ipping: [172.16.1.8]
    fatal: [172.16.1.7]: FAILED! => {"changed": true, "cmd": "rsync -avz /tmp/test_web01.txt rsync_backup@172.16.1.151::backup --password-file=/etc/rsync.password", "delta": "0:00:00.056712", "end": "2020-05-06 17:20:20.672234", "msg": "non-zero return code", "rc": 10, "start": "2020-05-06 17:20:20.615522", "stderr": "rsync: failed to connect to 172.16.1.151 (172.16.1.151): Connection refused (111)
    rsync error: error in socket IO (code 10) at clientserver.c(125) [sender=3.1.2]", "stderr_lines": ["rsync: failed to connect to 172.16.1.151 (172.16.1.151): Connection refused (111)", "rsync error: error in socket IO (code 10) at clientserver.c(125) [sender=3.1.2]"], "stdout": "", "stdout_lines": []}
    
    TASK [check test bata] **************************************************************************************************************
    fatal: [172.16.1.8]: FAILED! => {"changed": true, "cmd": "rsync -avz /tmp/test_web02.txt rsync_backup@172.16.1.151::data --password-file=/etc/rsync.password", "delta": "0:00:00.055521", "end": "2020-05-06 17:20:21.207470", "msg": "non-zero return code", "rc": 10, "start": "2020-05-06 17:20:21.151949", "stderr": "rsync: failed to connect to 172.16.1.151 (172.16.1.151): Connection refused (111)
    rsync error: error in socket IO (code 10) at clientserver.c(125) [sender=3.1.2]", "stderr_lines": ["rsync: failed to connect to 172.16.1.151 (172.16.1.151): Connection refused (111)", "rsync error: error in socket IO (code 10) at clientserver.c(125) [sender=3.1.2]"], "stdout": "", "stdout_lines": []}
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.151               : ok=9    changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.7                 : ok=4    changed=1    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
    172.16.1.8                 : ok=4    changed=1    unreachable=0    failed=1    skipped=1    rescued=0    ignored=0 
    #因为改了端口所以有报错是正常的
    
    1. 测试未触发
    [root@m01 /etc/ansible/yaml]# ansible-playbook ./rsync.yaml 
    
    PLAY [172.16.1.151] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [push copy config & password] **************************************************************************************************
    ok: [172.16.1.151] => (item={u'dest': u'rsyncd.conf', u'src': u'rsyncd.conf', u'mode': 644})
    ok: [172.16.1.151] => (item={u'dest': u'rsync.password', u'src': u'rsync.password', u'mode': 600})
    
    TASK [useradd rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create backup file & create backup file] **************************************************************************************
    ok: [172.16.1.151] => (item={u'owner': u'rsync', u'path': u'/backup', u'state': u'directory', u'group': u'rsync'})
    ok: [172.16.1.151] => (item={u'owner': u'rsync', u'path': u'/data', u'state': u'directory', u'group': u'rsync'})
    
    TASK [systemctl start rsyncd] *******************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [check port] *******************************************************************************************************************
    fatal: [172.16.1.151]: FAILED! => {"changed": true, "cmd": "netstat -luntp|grep 873", "delta": "0:00:00.060750", "end": "2020-05-06 17:38:37.720858", "msg": "non-zero return code", "rc": 1, "start": "2020-05-06 17:38:37.660108", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.151               : ok=6    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
    #文件没有发生改变,所以未触发,报错是因为改端口的原因
    

    5.1.9 剧本整合在一起,一键安装

    1. 整合rsync和nfs 剧本
    - import_playbook: rsync.yaml
    - import_playbook: nfs.yaml
    
    1. 测试
    [root@m01 /etc/ansible/yaml]# ansible-playbook ./rsync_nfs.yaml
    
    PLAY [172.16.1.151] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [push copy config & password] **************************************************************************************************
    ok: [172.16.1.151] => (item={u'dest': u'rsyncd.conf', u'src': u'rsyncd.conf', u'mode': 644})
    ok: [172.16.1.151] => (item={u'dest': u'rsync.password', u'src': u'rsync.password', u'mode': 600})
    
    TASK [useradd rsync] ****************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create backup file & create backup file] **************************************************************************************
    ok: [172.16.1.151] => (item={u'owner': u'rsync', u'path': u'/backup', u'state': u'directory', u'group': u'rsync'})
    changed: [172.16.1.151] => (item={u'owner': u'rsync', u'path': u'/data', u'state': u'directory', u'group': u'rsync'})
    
    TASK [systemctl start rsyncd] *******************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [check port] *******************************************************************************************************************
    changed: [172.16.1.151]
    
    TASK [display port info] ************************************************************************************************************
    ok: [172.16.1.151] => {
        "msg": [
            "tcp        0      0 0.0.0.0:873             0.0.0.0:*               LISTEN      51539/rsync         ", 
            "tcp6       0      0 :::873                  :::*                    LISTEN      51539/rsync         "
        ]
    }
    
    PLAY [rsync_client] *****************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [install rsync] ****************************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [create password file] *********************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [create web01 file & create web01 file] ****************************************************************************************
    changed: [172.16.1.7] => (item={u'dest': u'test_web01.txt', u'state': u'touch'})
    changed: [172.16.1.8] => (item={u'dest': u'test_web01.txt', u'state': u'touch'})
    changed: [172.16.1.7] => (item={u'dest': u'test_web02.txt', u'state': u'touch'})
    changed: [172.16.1.8] => (item={u'dest': u'test_web02.txt', u'state': u'touch'})
    
    TASK [check test backup & check test data] ******************************************************************************************
    skipping: [172.16.1.8]
    changed: [172.16.1.7]
    
    TASK [check test bata] **************************************************************************************************************
    skipping: [172.16.1.7]
    changed: [172.16.1.8]
    
    PLAY [nfs] **************************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [nfs install] ******************************************************************************************************************
    ok: [172.16.1.151]
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    PLAY [nfs_server] *******************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [copy conf file] ***************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [create data dir] **************************************************************************************************************
    changed: [172.16.1.151]
    
    TASK [nfs-utils & rpcbind start] ****************************************************************************************************
    ok: [172.16.1.151] => (item=rpcbind)
    ok: [172.16.1.151] => (item=nfs)
    
    PLAY [nfs_client] *******************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [start rpcbind] ****************************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [mount] ************************************************************************************************************************
    changed: [172.16.1.8]
    changed: [172.16.1.7]
    
    TASK [check mount] ******************************************************************************************************************
    changed: [172.16.1.7]
    changed: [172.16.1.8]
    
    TASK [display mount info] ***********************************************************************************************************
    ok: [172.16.1.7] => {
        "msg": [
            "172.16.1.31:/data              19G  2.1G   17G  12% /data", 
            "172.16.1.61:/data              19G  2.3G   17G  13% /mnt"
        ]
    }
    ok: [172.16.1.8] => {
        "msg": [
            "172.16.1.31:/data              19G  2.1G   17G  12% /data", 
            "172.16.1.61:/data              19G  2.3G   17G  13% /mnt"
        ]
    }
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.151               : ok=14   changed=3    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.7                 : ok=12   changed=4    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    172.16.1.8                 : ok=12   changed=4    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   
    

    5.1.10 ansible程序roles(角色) 使用

    1. ansible程序roles(角色) --- 规范
        1. 规范目录结构
        2. 在roles目录中创建相关文件
        3. 服务端配置文件改动,客户端参数信息也自动变化
        4. 汇总剧本中没有显示主机角色信息
        5. 一个剧本内容信息过多,不容易进行阅读,如何进行拆分	 
    
    [root@m01 /etc/ansible/yaml]# cd ../roles/
    [root@m01 /etc/ansible/roles]# mkdir -p {rsync,nfs}/{files,tasks,handlers,vars,templates}
    [root@m01 /etc/ansible/roles]# tree
    .
    ├── nfs
    │   ├── files
    │   ├── handlers
    │   ├── tasks
    │   ├── templates
    │   └── vars
    └── rsync
        ├── files
        ├── handlers
        ├── tasks
        ├── templates
        └── vars
    ##目录说明
     .
        ├── nfs
        │   ├── files       --- 保存需要分发文件目录 
        │   ├── handlers	--- 保存触发器配置文件信息
        │   ├── tasks       --- 保存要执行的动作信息文件   
        │   ├── templates   --- 保存需要分发模板文件 模板文件中可以设置变量信息
        │   └── vars        --- 保存变量信息文件
    
    1. 有客户端和服务端的服务需要这样创建
    [root@m01 /etc/ansible/roles]# tree
    .
    ├── nfs_client
    │   ├── files
    │   ├── handlers
    │   ├── tasks
    │   ├── templates
    │   └── vars
    ├── nfs_server
    │   ├── files
    │   ├── handlers
    │   ├── tasks
    │   ├── templates
    │   └── vars
    ├── rsync_client
    │   ├── files
    │   ├── handlers
    │   ├── tasks
    │   ├── templates
    │   └── vars
    └── rsync_server
        ├── files
        ├── handlers
        ├── tasks
        ├── templates
        └── vars
    
    1. nfs 一键安装的拆分
    .
    ├── nfs_all
    │   ├── files
    │   ├── handlers
    │   ├── tasks
    │   │   └── main.yaml
    │   ├── templates
    │   └── vars
    ├── nfs_client
    │   ├── files
    │   ├── handlers
    │   ├── tasks
    │   │   └── main.yaml
    │   ├── templates  #(存放变化的文件模板)使用模板模块命令的方法:ansible-doc template
    │   └── vars
    │       └── main.yaml
    ├── nfs_server
    │   ├── files
    │   │   └── exports
    │   ├── handlers
    │   │   └── main.yml
    │   ├── tasks
    │   │   └── main.yml
    │   ├── templates
    │   └── vars
    │       └── main.yml
    
    1. 测试效果
    [root@m01 /etc/ansible/roles]# ansible-playbook site.yaml 
    
    PLAY [nfs] **************************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.8]
    ok: [172.16.1.151]
    ok: [172.16.1.7]
    
    TASK [nfs_all : nfs install] ********************************************************************************************************
    ok: [172.16.1.151]
    ok: [172.16.1.8]
    ok: [172.16.1.7]
    
    PLAY [nfs_server] *******************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [nfs_server : copy conf file] **************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [nfs_server : create data dir] *************************************************************************************************
    ok: [172.16.1.151]
    
    TASK [nfs_server : nfs-utils & rpcbind start] ***************************************************************************************
    ok: [172.16.1.151] => (item=rpcbind)
    ok: [172.16.1.151] => (item=nfs)
    
    PLAY [nfs_client] *******************************************************************************************************************
    
    TASK [Gathering Facts] **************************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [nfs_client : start rpcbind] ***************************************************************************************************
    ok: [172.16.1.7]
    ok: [172.16.1.8]
    
    TASK [nfs_client : mount] ***********************************************************************************************************
    changed: [172.16.1.8]
    changed: [172.16.1.7]
    
    TASK [nfs_client : check mount] *****************************************************************************************************
    changed: [172.16.1.7]
    changed: [172.16.1.8]
    
    TASK [nfs_client : display mount info] **********************************************************************************************
    ok: [172.16.1.7] => {
        "msg": [
            "172.16.1.31:/data              19G  2.1G   17G  12% /data", 
            "172.16.1.61:/data              19G  2.3G   17G  13% /mnt"
        ]
    }
    ok: [172.16.1.8] => {
        "msg": [
            "172.16.1.31:/data              19G  2.1G   17G  12% /data", 
            "172.16.1.61:/data              19G  2.3G   17G  13% /mnt"
        ]
    }
    
    PLAY RECAP **************************************************************************************************************************
    172.16.1.151               : ok=6    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.7                 : ok=7    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
    172.16.1.8                 : ok=7    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0  
    

    调用模板文件的模块

    [root@m01 /etc/ansible/roles]# ansible-doc template
    
  • 相关阅读:
    discuz 门户功能增加自定义keywords字段
    discuz的门户文章页中增加百度分享代码
    discuz 门户页模板中的keywords和description不能正常显示
    windows下python的安装
    discuz 取消门户首页url中的portal.php
    网站被跳转到联通域名无法访问页面
    DedeCms密码解密[转]
    last error : SSL certificate problem, verify that the CA cert is OK. Details: error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate veri
    [转]解决MySQL出现大量unauthenticated user的问题
    ImageUtils
  • 原文地址:https://www.cnblogs.com/woaiyunwei/p/13140429.html
Copyright © 2011-2022 走看看