ansible批量管理服务入门

onepiecedn 2020-01-28

2020-01-17

此为ansible批量管理服务的第1个博客,发布博客为ansible批量管理服务入门


综合架构(二)——ansible批量管理服务

一ansible批量管理服务功能


01.可以实现批量系统操作配置
02.可以实现批量软件服务部署
03.可以实现批量文件数据分发
04.可以实现批量系统信息收集,资产管理

二ansible批量管理服务特点


01.管理端不需要启动服务程序(no server)
02.管理端不需要编写配置文件(/etc/ansible/ansible.cfg)
03.受控端不需要安装软件程序(libselinux-python)
04.受控端不需要启动服务程序(no agent)
05.服务程序管理操作模块众多(module)
06.利用剧本编写来实现自动化(playbook)

三批量管理软件安装部暑过程

[ ~]# yum install   -y ansible
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
 * base: mirrors.aliyun.com
 * extras: mirrors.aliyun.com
 * updates: mirrors.aliyun.com
base                                                   | 3.6 kB     00:00     
epel                                                   | 5.4 kB     00:00     
extras                                                 | 2.9 kB     00:00     
updates                                                | 2.9 kB     00:00     
(1/2): epel/x86_64/updateinfo                            | 1.0 MB   00:01     
(2/2): epel/x86_64/primary_db                            | 6.9 MB   00:02     
Package ansible-2.9.2-1.el7.noarch already installed and latest version
Nothing to do

涉及到的组件非常多

[ ~]# rpm  -ql  ansible   |  wc
  17280   17280 1446145
[ ~]# rpm  -ql  ansible   |  head
/etc/ansible
/etc/ansible/ansible.cfg
/etc/ansible/hosts
/etc/ansible/roles
/usr/bin/ansible
/usr/bin/ansible-2
/usr/bin/ansible-2.7
/usr/bin/ansible-config
/usr/bin/ansible-connection
/usr/bin/ansible-console
[ ~]# rpm  -ql  ansible   |  tail
/usr/share/doc/ansible-2.9.2/README.rst
/usr/share/man/man1/ansible-config.1.gz
/usr/share/man/man1/ansible-console.1.gz
/usr/share/man/man1/ansible-doc.1.gz
/usr/share/man/man1/ansible-galaxy.1.gz
/usr/share/man/man1/ansible-inventory.1.gz
/usr/share/man/man1/ansible-playbook.1.gz
/usr/share/man/man1/ansible-pull.1.gz
/usr/share/man/man1/ansible-vault.1.gz
/usr/share/man/man1/ansible.1.gz
[ ~]#

查看ansible的版本

版本很重要,因为有些服务的版本可能隔一段时间就会发生变化,相关的功能也会变化

[ ~]# ansible  --version
ansible 2.9.2
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u‘/root/.ansible/plugins/modules‘, u‘/usr/share/ansible/plugins/modules‘]
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Oct 30 2018, 23:45:53) [GCC 4.8.5 20150623 (Red Hat 4.8.5-36)]

注意只能使用长格式查看

[ ~]# ansible  -V
usage: ansible [-h] [--version] [-v] [-b] [--become-method BECOME_METHOD]
               [--become-user BECOME_USER] [-K] [-i INVENTORY] [--list-hosts]
               [-l SUBSET] [-P POLL_INTERVAL] [-B SECONDS] [-o] [-t TREE] [-k]
               [--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER]
               [-c CONNECTION] [-T TIMEOUT]
               [--ssh-common-args SSH_COMMON_ARGS]
               [--sftp-extra-args SFTP_EXTRA_ARGS]
               [--scp-extra-args SCP_EXTRA_ARGS]
               [--ssh-extra-args SSH_EXTRA_ARGS] [-C] [--syntax-check] [-D]
               [-e EXTRA_VARS] [--vault-id VAULT_IDS]
               [--ask-vault-pass | --vault-password-file VAULT_PASSWORD_FILES]
               [-f FORKS] [-M MODULE_PATH] [--playbook-dir BASEDIR]
               [-a MODULE_ARGS] [-m MODULE_NAME]
               pattern
ansible: error: too few arguments
[ ~]# ansible  -v
usage: ansible [-h] [--version] [-v] [-b] [--become-method BECOME_METHOD]
               [--become-user BECOME_USER] [-K] [-i INVENTORY] [--list-hosts]
               [-l SUBSET] [-P POLL_INTERVAL] [-B SECONDS] [-o] [-t TREE] [-k]
               [--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER]
               [-c CONNECTION] [-T TIMEOUT]
               [--ssh-common-args SSH_COMMON_ARGS]
               [--sftp-extra-args SFTP_EXTRA_ARGS]
               [--scp-extra-args SCP_EXTRA_ARGS]
               [--ssh-extra-args SSH_EXTRA_ARGS] [-C] [--syntax-check] [-D]
               [-e EXTRA_VARS] [--vault-id VAULT_IDS]
               [--ask-vault-pass | --vault-password-file VAULT_PASSWORD_FILES]
               [-f FORKS] [-M MODULE_PATH] [--playbook-dir BASEDIR]
               [-a MODULE_ARGS] [-m MODULE_NAME]
               pattern
ansible: error: too few arguments

 ansible软件学习说明:
1) 掌握ansible主机清单配置:  指定ansible程序可以批量管理哪些主机
       https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html
2) 掌握ansible常用功能模块:  实现批量管理功能模块
       https://docs.ansible.com/ansible/latest/modules/modules_by_category.html
3) 掌握ansible剧本编写方法:  实现自动化批量管理功能
       https://docs.ansible.com/ansible/latest/user_guide/playbooks.html

四网站主机清单配置

(一)方式一:直接在配置文件/etc/ansible/hosts写入主机地址

[ ~]# tail  /etc/ansible/hosts

# Here‘s another example of host ranges, this time there are no
# leading 0s:

## db-[99:101]-node.example.com

172.16.1.7
172.16.1.8
172.16.1.31
172.16.1.41

m表示module

[ ~]# ansible  --help  |  grep  "\-m "
               [-a MODULE_ARGS] [-m MODULE_NAME]
  -m MODULE_NAME, --module-name MODULE_NAME

在命令行检测

ping 模块:测试主机之间的连通性

参考:https://docs.ansible.com/ansible/latest/modules/ping_module.html#ping-module

[ ~]# ansible  all -m  ping
172.16.1.41 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
172.16.1.7 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
172.16.1.31 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
172.16.1.8 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[ ~]# ansible   172.16.1.8  -m    ping
172.16.1.8 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[ ~]# ansible   172.16.1.7  -m    ping
172.16.1.7 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[ ~]# ansible   172.16.1.31  -m    ping
172.16.1.31 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[ ~]# ansible   172.16.1.41  -m    ping
172.16.1.41 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[ ~]#

注意命令的顺序不能写错的

[ ~]# ansible  -m  172.16.1.7 ping
[WARNING]: Could not match supplied host pattern, ignoring: ping

[WARNING]: No hosts matched, nothing to do

[ ~]# ansible  -m  172.16.1.8   ping
[WARNING]: Could not match supplied host pattern, ignoring: ping

[WARNING]: No hosts matched, nothing to do

[ ~]#

(二)方式二:基于密码方式进行配置

参考官网,比较麻烦

把公钥删除,这是在受控端没有管理端的公钥的情况下配置的

以备份服务器为受控端

[ ~]# ip  a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:b9:d6:60 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.31/24 brd 10.0.0.255 scope global noprefixroute eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::d2e4:6879:ac85:c625/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::8c8d:c31b:a121:ca62/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::9d5f:63cb:4c46:8ce7/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:b9:d6:6a brd ff:ff:ff:ff:ff:ff
    inet 172.16.1.31/24 brd 172.16.1.255 scope global noprefixroute eth1
       valid_lft forever preferred_lft forever
    inet6 fe80::e654:55e2:8c88:ecfb/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::5e65:529b:4fae:7fc3/64 scope link tentative noprefixroute dadfailed 
       valid_lft forever preferred_lft forever
    inet6 fe80::787b:a3a1:ead:b12e/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
[ ~]# ls  /root/.ssh/
authorized_keys
[ ~]# ll  /root/.ssh/
-bash: ll: command not found
[ ~]# ls  -l  /root/.ssh/  
total 4
-rw------- 1 root root 394 Jan 16 22:47 authorized_keys
[ ~]# cat  /root/.ssh/authorized_keys 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDhE06kiM6UKlnZqGPBahZuAgq+LHdSssZrInWpkecC5buh2RRzl2NOiXCWNhEIwNgIJjLGsnITrTOyRsOel94oUYHR4iSPPhAe8yVuTZA8fS9ti1goIKt6/UYhi6bbNmFiqWPlSq1EIgpNvlWaDjHIchdIHR/lbgP3Wjg2PPI2QtzR5/SZJOI0g/GTJw1FDGXpYUlz608YTo79tl15zUAGT5rLiu5ugXY28HGQbPru5xA+BQZyzKu4jInllM8WzLimpFb7WX8HagwSU2S/Hx2+HSzEbMHXqz0tm8WbQogEO78gv0cJ6USq8vyc1ueq/Jn27gDu3ygPXtcSCn0XKpZJ
[ ~]# tail -1  /etc/ansible/hosts 
172.16.1.31
[ ~]#  ansible  172.16.1.31 -m  ping
172.16.1.31 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

删除受控端的管理端对应的公钥

[ ~]# rm  -f  /root/.ssh/authorized_keys
[ ~]# ls  /root/.ssh/authorized_keys
ls: cannot access /root/.ssh/authorized_keys: No such file or directory

此时管理端要输入密码才可以登录到受控端

[ ~]# ssh  172.16.1.31
172.16.1.31‘s password: 
Last login: Sun Jan 26 17:30:17 2020 from 172.16.1.61
[ ~]# exit 
logout
Connection to 172.16.1.31 closed.

修改配置文件并且进行

[ ~]# tail -1  /etc/ansible/hosts 
172.16.1.31  ansible_user=root  ansible_password=123456  ansible_port=22
[ ~]#  ansible  172.16.1.31 -m  ping
172.16.1.31 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

 ansible批量管理服务入门

(三)方式三: 采用主机组方式配置

分组进行操作,和班级进行分组管理一样,管理起来更加方便

[ ~]# tail  /etc/ansible/hosts

## db-[99:101]-node.example.com

[web]
172.16.1.7
172.16.1.8
[nfs]
172.16.1.31
[backup]
172.16.1.41

执行命令

[ ~]# ansible   web  -m    ping
172.16.1.7 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
172.16.1.8 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[ ~]# ansible   nfs  -m    ping
172.16.1.31 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[ ~]# ansible   backup  -m    ping
172.16.1.41 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

主机子组配置,对组进行管理

[ ~]# tail   -15   /etc/ansible/hosts
# leading 0s:

## db-[99:101]-node.example.com

[client:children]
web
nfs
backup
[web]
172.16.1.7
172.16.1.8
[nfs]
172.16.1.31
[backup]
172.16.1.41

 执行命令

[ ~]# ansible   client   -m    ping
172.16.1.31 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
172.16.1.7 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
172.16.1.8 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
172.16.1.41 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

(四)方式四:采用匹配方式配置主机信息

 [7:20]表示IP地址最后一位为7到20的主机

[ ~]# tail  -1    /etc/ansible/hosts
172.16.1.[7:20]

执行命令

31,41没有匹配

[ ~]# ansible   172.16.1.7  -m    ping
172.16.1.7 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[ ~]# ansible   172.16.1.8  -m    ping
172.16.1.8 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[ ~]# ansible   172.16.1.31  -m    ping
[WARNING]: Could not match supplied host pattern, ignoring: 172.16.1.31

[WARNING]: No hosts matched, nothing to do

[ ~]# ansible   172.16.1.41  -m    ping
[WARNING]: Could not match supplied host pattern, ignoring: 172.16.1.41

[WARNING]: No hosts matched, nothing to do
[ ~]# tail  -1    /etc/ansible/hosts
172.16.1.[1:20]
[ ~]# ansible   172.16.1.7  -m    ping
172.16.1.7 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[ ~]# ansible   172.16.1.8  -m    ping
172.16.1.8 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
[ ~]# ansible   172.16.1.31  -m    ping
[WARNING]: Could not match supplied host pattern, ignoring: 172.16.1.31

[WARNING]: No hosts matched, nothing to do

[ ~]# ansible   172.16.1.41  -m    ping
[WARNING]: Could not match supplied host pattern, ignoring: 172.16.1.41

[WARNING]: No hosts matched, nothing to do

五批量管理服务应用方法


批量管理命令语法结构:

ansible      管理主机信息/主机组信息    -m    模块名称    -a     "模块参数"

[ ~]# tail     /etc/ansible/hosts

# Here‘s another example of host ranges, this time there are no
# leading 0s:

## db-[99:101]-node.example.com
[client]
172.16.1.7
172.16.1.8
172.16.1.31
172.16.1.41

(一)command模块 (默认)

[ ~]# ansible client  -a  "free -h"
172.16.1.7 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           972M        138M        591M        7.7M        242M        651M
Swap:          1.5G          0B        1.5G

172.16.1.31 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           972M        140M        642M        7.7M        189M        647M
Swap:          1.5G          0B        1.5G

172.16.1.41 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           972M        136M        673M        7.7M        162M        665M
Swap:          1.5G          0B        1.5G

172.16.1.8 | CHANGED | rc=0 >>
              total        used        free      shared  buff/cache   available
Mem:           972M        140M        662M        7.7M        169M        657M
Swap:          1.5G          0B        1.5G
[ ~]# ansible client -m  shell   -a  "rm  -rf  /tmp/*"
[WARNING]: Consider using the file module with state=absent rather than running
‘rm‘.  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.7 | CHANGED | rc=0 >>


172.16.1.8 | CHANGED | rc=0 >>


172.16.1.31 | CHANGED | rc=0 >>


172.16.1.41 | CHANGED | rc=0 >>


[ ~]# ansible client -m  shell   -a  "ls  /tmp/*"
172.16.1.8 | CHANGED | rc=0 >>
ansible_command_payload.zip

172.16.1.7 | CHANGED | rc=0 >>
ansible_command_payload.zip

172.16.1.41 | CHANGED | rc=0 >>
ansible_command_payload.zip

172.16.1.31 | CHANGED | rc=0 >>
ansible_command_payload.zip
[ ~]# ansible client -m  command   -a  "pwd"
172.16.1.41 | CHANGED | rc=0 >>
/root

172.16.1.7 | CHANGED | rc=0 >>
/root

172.16.1.8 | CHANGED | rc=0 >>
/root

172.16.1.31 | CHANGED | rc=0 >>
/root

模块参数:chdir:  在执行批量管理命令时, 先进行目录切换        

[ ~]# ansible   client  -m   command   -a  "chdir=/tmp pwd"
172.16.1.41 | CHANGED | rc=0 >>
/tmp

172.16.1.7 | CHANGED | rc=0 >>
/tmp

172.16.1.31 | CHANGED | rc=0 >>
/tmp

172.16.1.8 | CHANGED | rc=0 >>
/tmp

creates: 判断指定文件是否存在, 如果不存在,就执行后面命令;存在就不执行后面命令

和判断语句类似

[ ~]# ansible client -m  command   -a  "creates=/tmp/happy.txt  touch /tmp/happy.txt"
[WARNING]: Consider using the file module with state=touch rather than running
‘touch‘.  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.31 | CHANGED | rc=0 >>


172.16.1.7 | CHANGED | rc=0 >>


172.16.1.41 | CHANGED | rc=0 >>


172.16.1.8 | CHANGED | rc=0 >>
[ ~]# ansible client -m  command   -a  "chdir=/tmp ls"
172.16.1.41 | CHANGED | rc=0 >>
ansible_command_payload_dKZhze
happy.txt

172.16.1.8 | CHANGED | rc=0 >>
ansible_command_payload_0Y2P6b
happy.txt

172.16.1.7 | CHANGED | rc=0 >>
ansible_command_payload_sagI1X
happy.txt

172.16.1.31 | CHANGED | rc=0 >>
ansible_command_payload_1XAqCp
happy.txt

再次执行会跳过了

[ ~]# ansible client -m  command   -a  "creates=/tmp/happy.txt  touch /tmp/happy.txt"
172.16.1.31 | SUCCESS | rc=0 >>
skipped, since /tmp/happy.txt exists

172.16.1.8 | SUCCESS | rc=0 >>
skipped, since /tmp/happy.txt exists

172.16.1.7 | SUCCESS | rc=0 >>
skipped, since /tmp/happy.txt exists

172.16.1.41 | SUCCESS | rc=0 >>
skipped, since /tmp/happy.txt exists

批量执行脚本


第一个步骤:编写脚本
第二个步骤:将脚本推送到被管理主机上
第三个步骤:将脚本文件权限进行设置
第四个步骤:批量执行脚本

 https://docs.ansible.com/ansible/latest/modules/shell_module.html#shell-module

(二)shell模块(万能模块)

作用说明:批量执行命令,可以识别特殊符号

[ ~]#  ansible-doc   --help |  grep  "\-s"
                   [-j] [-F | -l | -s | --metadata-dump]
                        prepend colon-separated path(s) to module library (def
  -s, --snippet         Show playbook snippet for specified plugin(s)
[ ~]# 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.
(END)

把管理端的脚本传输到受控端的目录里面

先查看目录是否存在

[ ~]# ansible  client  -m  shell  -a  "ls  -d  /shell_scripts"
172.16.1.8 | CHANGED | rc=0 >>
/shell_scripts

172.16.1.7 | CHANGED | rc=0 >>
/shell_scripts

172.16.1.31 | CHANGED | rc=0 >>
/shell_scripts

172.16.1.41 | CHANGED | rc=0 >>
/shell_scripts

正式进行文件传输

[ ~]# time   ansible  client  -m  copy    -a  ‘src=/shell_scripts/install.sh  dest=/shell_scripts‘
172.16.1.41 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "checksum": "d8930d18657635c362456d4e25091679006031e8", 
    "dest": "/shell_scripts/install.sh", 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/shell_scripts/install.sh", 
    "size": 36, 
    "state": "file", 
    "uid": 0
}
172.16.1.7 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "checksum": "d8930d18657635c362456d4e25091679006031e8", 
    "dest": "/shell_scripts/install.sh", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "path": "/shell_scripts/install.sh", 
    "size": 36, 
    "state": "file", 
    "uid": 0
}
172.16.1.31 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "checksum": "d8930d18657635c362456d4e25091679006031e8", 
    "dest": "/shell_scripts/install.sh", 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/shell_scripts/install.sh", 
    "size": 36, 
    "state": "file",

相关推荐