本人playbook例子
https://github.com/aawuliliaa/ansible/tree/master/playbook

1.1批量管理服务知识介绍

a. ansible是一个基于Python开发的自动化运维工具
b. ansible是一个基于ssh协议实现远程管理的工具
c. ansible软件可以实现多种批量管理操作(批量系统配置、批量软件部署、批量文件拷贝、批量运行命令)

1.2批量管理服务特征介绍

a ansible软件服务端(管理端):不需要启动任何服务 默认服务端不需要任何的配置
b ansible软件客户端(受控端):没有客户端软件安装

1.3ansible软件安装部署

1.3.1 ansible软件自动化环境架构规划

  管理主机1台:
  10.0.0.61   m01
  受控主机3台:
  10.0.0.41   backup
  10.0.0.31   nfs01
  10.0.0.7    web01
  Linux系统 6.9

1.3.2ansible软件自动化部署条件

1.ssh密钥对创建(管理主机)
ssh-keygen -t dsa
影响免交互创建密钥对创建因素:
1)需要指定私钥存放路径
   -f /root/.ssh/id_dsa
2)需要进行私钥文件密码设定
   -N/-P  
   -N ""/-P ""

2.免交互创建密钥对方法
ssh-keygen -t dsa -f /root/.ssh/id_dsa -N ""

3.分发公钥文件(管理主机进行分发)
ssh-copy-id -i /root/.ssh/id_dsa.pub 172.16.1.31
影响免交互批量分发密钥因素
1)需要有确认连接过程,需要输入yes/no
   man ssh查找到下面的-o选项
   -o StrictHostKeyChecking=no
   sshpass -p123456 ssh-copy-id -i /root/.ssh/id_dsa.pub "-o StrictHostKeyChecking=no 172.16.1.31"

2)需要解决密码问题
   sshpass -p123456 ssh-copy-id -i /root/.ssh/id_dsa.pub 172.16.1.31
   Now try logging into the machine, with "ssh '172.16.1.31'", and check in:

     .ssh/authorized_keys

   to make sure we haven't added extra keys that you weren't expecting.

3.免交互批量分发公钥脚本
#!/bin/bash
rm /root/.ssh/id_dsa
ssh-keygen -t dsa -f /root/.ssh/id_dsa -N ""

for ip in 31 41 7
do
sshpass -p123456 ssh-copy-id -i /root/.ssh/id_dsa.pub "-o StrictHostKeyChecking=no 172.16.1.$ip"
done

4.检查是否可以进行基于密钥远程管理
ssh 172.16.1.31 uptime
免交互批量检查测试脚本
#!/bin/bash
#description:back file to the directory of /backup
#author:vita
#time:2019-03-04
[ $# -ne 1 ]&&echo "you should use this script like sh fenfa_check.sh pwd"&&exit
for ip in 31 41 7
do
    echo "start to excute 172.16.1.$ip"
    ssh 172.16.1.$ip $1
    echo "172.16.1.$ip end"
done

5.服务器端口默认不是22怎样执行ssh-copy-id 
[root@m01 scripts]# which ssh-copy-id
/usr/bin/ssh-copy-id    
[root@m01 scripts]# vim /usr/bin/ssh-copy-id            
{ eval "$GET_ID" ; } | ssh $1 "exec sh -c 'cd; umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys && (test -x /sbin/restorecon && /sbin/restorecon .ssh .ssh/authorized_keys >/dev/null 2>&1 || true)'" || exit 1
方法一:
{ eval "$GET_ID" ; } | ssh -p52113 $1 "exec sh -c 'cd; umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys && (test -x /sbin/restorecon && /sbin/restorecon .ssh .ssh/authorized_keys >/dev/null 2>&1 || true)'" || exit 1
1.临时设置umask值
2.利用脚本创建.ssh目录 test -d ~/.ssh||mkdir ~/.ssh
3.将本地公钥文件中的信息重定向到远程主机的.ssh/authorized_keys文件中,并授权为600
说明:通过对ssh-copy-id命令文件信息改写,是可以实现被管理主机不同端口号情况,顺利分发公钥信息
上面方法不是最好,如果别人不了解这个知识,修改了端口后又要重新处理。

方法二:
最好的方法
ssh-copy-id -i /root/.ssh/id_sda.pub "172.16.1.31 -p52113"

详细解析如下:
shift要在脚本中应用时,会将传参的参数依次向前推进
#!/bin/bash
#description:back file to the directory of /backup
#author:vita
#time:2019-03-04
until [ $# -eq 0 ]
do
    echo $*
    shift
done

[root@m01 scripts]# sh shift.sh 1 2 3 4 5
1 2 3 4 5
2 3 4 5
3 4 5
4 5
5      
由于/usr/bin/ssh-copy-id脚本中上面用了两个shift,
if [ "-i" = "$1" ]; then
  shift
  # check if we have 2 parameters left, if so the first is the new ID file
  if [ -n "$2" ]; then
    if expr "$1" : ".*\.pub" > /dev/null ; then
      ID_FILE="$1"
    else
      ID_FILE="$1.pub"
    fi
    shift         # and this should leave $1 as the target name
  fi
所以
ssh-copy-id -i /root/.ssh/id_sda.pub "172.16.1.31 -p52113"中 "172.16.1.31 -p52113"就变成了$1,
所以{ eval "$GET_ID" ; } | ssh $1 "exec sh -c 'cd; umask 077; test -d .ssh || mkdir .ssh ; cat >> .ssh/authorized_keys && (test -x /sbin/restorecon && /sbin/restorecon .ssh .ssh/authorized_keys >/dev/null 2>&1 || true)'" || exit 1这里的-p52113就给了这里的ssh命令
这也是上面脚本sshpass -p123456 ssh-copy-id -i /root/.ssh/id_dsa.pub "-o StrictHostKeyChecking=no 172.16.1.31"这样书写的原因

1.3.3ansible软件下载安装

ansible管理主机软件安装:
yum install -y ansible
ansible受控主机软件安装:(可选)
yum install -y libselinux-python

1.3.4ansible软件hosts配置文件

#这种是已经配置了互相的免密登录方式
cat /etc/ansible/hosts
[oldboy]
172.16.1.7
172.16.1.31
172.16.1.41

vim /etc/ansible/hosts
[oldboy]
172.16.1.7
172.16.1.31 ansible_user=root ansible_password=123456
#1.ssh用户+ssh秘码
#10.0.0.62 ansible_ssh_user=root ansible_ssh_pass=123456

#2.ssh用户+ssh秘钥,我配置了怎么都不好使呢。。。。。。。
#10.0.0.62 ansible_ssh_user=root  ansible_ssh_private_key_file=/root/.ssh/id_dsa
#/root/.ssh/id_dsa我配置的是ansible服务端root用户的私钥地址
#3.别名+ssh用户+ssh秘钥
m02 ansible_ssh_host=10.0.0.62 ansible_ssh_user=root  ansible_ssh_private_key_file=/root/.ssh/id_dsa
[root@m01 playbook]# ansible all --list-hosts
  hosts (3):
    10.0.0.61
    10.0.0.62
    172.16.1.61

ansible 172.16.1.31 -m command -a "hostname" -k     --- 实现口令交互式远程管理
SSH password: 
172.16.1.31 | SUCCESS | rc=0 >>
nfs01
#group组包含php和nginx
/etc/ansible/hosts
10.0.0.61
[db]
172.16.1.61
[php]
172.16.1.61
[nginx]
10.0.0.62 ansible_ssh_user=root  ansible_ssh_pass=123456
[group:children]
php
nginx

# -f是5个并发,-l是只展示该主机的信息
[root@m01 playbook]# ansible group -m shell -a "ls -l /opt" -f 5 -l 10.0.0.62
10.0.0.62 | SUCCESS | rc=0 >>
total 8
-rw-r--r-- 1 root root 498 Aug  1 18:51 hosts
drwxr-xr-x 4 root root  33 Apr  3 10:46 script
drwxr-xr-x 2 root root   6 Aug  1 18:44 sd
-rw-r--r-- 1 root root 168 Aug  1 18:40 sum.sh

1.4ansible软件模块详解

ansible软件模块
ansible-doc -l|wc -l
1378

ansible 管理主机信息或者主机组信息  -m 模块名称 -a 相关模块参数

主机信息:远程主机IP地址  远程主机组名称  远程所有主机all
-m 指定相应模块
-a 利用模块中某些参数功能

1.4.1第一个模块:command

官方参考链接:http://docs.ansible.com/ansible/latest/modules/command_module.html
参数:chdir---在执行莫个命令前,先切换目录
[root@m01 ansible]# ansible 172.16.1.31 -m command -a "chdir=/tmp/ pwd"
172.16.1.31 | SUCCESS | rc=0 >>
/tmp

[root@m01 ansible]# ansible 172.16.1.31 -m command -a "chdir=/etc/ pwd"
172.16.1.31 | SUCCESS | rc=0 >>
/etc

参数:creates---判断一个文件是否存在,如果已经存在了,后面的命令就不会执行
[root@m01 ansible]# ansible 172.16.1.41 -m command -a "creates=/etc/rsyncd.conf hostname"
172.16.1.41 | SUCCESS | rc=0 >>
skipped, since /etc/rsyncd.conf exists

[root@m01 ansible]# ansible 172.16.1.41 -m command -a "creates=/etc/rsyncd.conf.bak hostname"
172.16.1.41 | SUCCESS | rc=0 >>
skipped, since /etc/rsyncd.conf.bak exists

[root@m01 ansible]# ansible 172.16.1.41 -m command -a "creates=/etc/rsyncd.123456 hostname"
172.16.1.41 | SUCCESS | rc=0 >>
backup

参数:removes---判断一个文件是否存在,如果不存在,后面的命令就不会执行
[root@m01 ansible]# ansible 172.16.1.41 -m command -a "removes=/etc/rsyncd.conf hostname"
172.16.1.41 | SUCCESS | rc=0 >>
backup

[root@m01 ansible]# ansible 172.16.1.41 -m command -a "removes=/etc/rsyncd.1212213123 hostname"
172.16.1.41 | SUCCESS | rc=0 >>
skipped, since /etc/rsyncd.1212213123 does not exist

参数(必须要有的):free_form---表示执行command模块时,必须要有linux合法命令信息
ansible 172.16.1.41 -m command -a "ls"
172.16.1.41 | SUCCESS | rc=0 >>
1
anaconda-ks.cfg
dead.letter
heqing

1.4.2第二个模块:shell模块(万能模块)

参数:chdir---在执行莫个命令前,先切换目录
参数:creates---判断一个文件是否存在,如果已经存在了,后面的命令就不会执行
参数:removes---判断一个文件是否存在,如果不存在,后面的命令就不会执行
参数(必须要有的):free_form---表示执行command模块时,必须要有linux合法命令信息
[root@m01 ansible]# ansible 172.16.1.41 -m shell -a "ls;pwd"
172.16.1.41 | SUCCESS | rc=0 >>
1
anaconda-ks.cfg
dead.letter
/root
说明:shell模块可以满足command模块所有功能,并且可以支持识别特殊字符信息 < > | ; 
[root@m01 ~]# ansible oldboy -m shell -a "cd /oldboy;ls -l"
172.16.1.41 | SUCCESS | rc=0 >>
total 4
drwxr-xr-x 2 root root 4096 Mar 11 17:58 sftp

172.16.1.31 | SUCCESS | rc=0 >>
total 12
-rw-r--r-- 1 root   root    285 Mar 11 17:59 back.sh
-rw-r--r-- 1 root   root      0 Mar 12 09:14 sftp
-rw-r--r-- 1 oldboy oldboy   20 Mar 11 17:39 test.log
drwxr-xr-x 3 root   root   4096 Mar  7 17:11 tmp

1.4.3第三个模块:script---在远程服务器上运行ansible服务端的脚本,远端不需要有该脚本

参数:chdir---在执行莫个命令前,先切换目录
参数:creates---判断一个文件是否存在,如果已经存在了,后面的命令就不会执行
参数:removes---判断一个文件是否存在,如果不存在,后面的命令就不会执行
参数(必须要有的):free_form---表示执行command模块时,必须要有linux合法命令信息

script模块与shell模块执行脚本的区别:
script模块只需要在管理主机本地有一个脚本,脚本中的命令就会在远程主机中执行
shell模块执行脚本,需要每个远程主机都有相同的脚本,否则无法执行

shell模块
[root@m01 ~]# ansible oldboy -m shell -a "cd /server/scripts;mv sum.sh sum.sh.bak"
172.16.1.31 | SUCCESS | rc=0 >>

172.16.1.41 | SUCCESS | rc=0 >>

[root@m01 ~]# ansible oldboy -m shell -a "cd /server/scripts;ls -l"
172.16.1.31 | SUCCESS | rc=0 >>
total 40
-rw-r--r--  1 root root  168 Mar 21  2019 sum.sh.bak
drwxr-xr-x  3 root root 4096 Mar 20  2019 var

172.16.1.41 | SUCCESS | rc=0 >>
total 36
-rw-r--r--  1 root root  168 Mar 21  2019 sum.sh.bak
drwxr-xr-x  3 root root 4096 Mar 20  2019 var
[root@m01 ~]# ansible oldboy -m shell -a "cd /server/scripts;sh sum.sh"
172.16.1.41 | FAILED | rc=127 >>
sh: sum.sh: No such file or directorynon-zero return code

172.16.1.31 | FAILED | rc=127 >>
sh: sum.sh: No such file or directorynon-zero return code
script模块
[root@m01 ~]# ansible oldboy -m script -a "/server/scripts/sum.sh"
172.16.1.31 | SUCCESS => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 172.16.1.31 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 172.16.1.31 closed."
    ], 
    "stdout": "5050\r\n", 
    "stdout_lines": [
        "5050"
    ]
}
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 172.16.1.41 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 172.16.1.41 closed."
    ], 
    "stdout": "5050\r\n", 
    "stdout_lines": [
        "5050"
    ]
}
[root@m01 ~]# ll /server/scripts/sum.sh 
-rw-r--r-- 1 root root 168 Mar 21  2019 /server/scripts/sum.sh

1.4.4copy----复制模块

参数:src---定义要推送数据信息
参数:dest---定义将数据推送到远程主机什么目录中
[root@m01 ansible]# touch /tmp/file01.txt
[root@m01 ansible]# ansible 172.16.1.41 -m copy -a "src=/tmp/file01.txt dest=/tmp/"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "checksum": "da39a3ee5e6b4b0d3255bfef95601890afd80709", 
    "dest": "/tmp/file01.txt", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "d41d8cd98f00b204e9800998ecf8427e", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "src": "/root/.ansible/tmp/ansible-tmp-1522682948.27-60532389065095/source", 
    "state": "file", 
    "uid": 0
}

参数:backup---对数据信息进行备份
[root@m01 ansible]# ansible 172.16.1.41 -m copy -a "src=/tmp/file01.txt dest=/tmp/ backup=yes"
172.16.1.41 | SUCCESS => {
    "backup_file": "/tmp/file01.txt.71887.2018-04-02@23:33:19~", 
    "changed": true, 
    "checksum": "029b054db136cc36d5605e3818305825ff4b8ffb", 
    "dest": "/tmp/file01.txt", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "434660b5ad7deeba8815349f71409405", 
    "mode": "0644", 
    "owner": "root", 
    "size": 6, 
    "src": "/root/.ansible/tmp/ansible-tmp-1522683197.05-52744169892601/source", 
    "state": "file", 
    "uid": 0
}

[root@m01 ansible]# ansible 172.16.1.41 -m shell -a "ls -l /tmp/"
172.16.1.41 | SUCCESS | rc=0 >>
total 24
-rw-r--r-- 1 root root    0 Apr  2 23:29 file01.txt
-rw-r--r-- 1 root root    0 Apr  2 23:29 /tmp/file01.txt.71887.2018-04-02@23:33:19~
参数:owner---设置复制后的文件属主权限
参数:group---设置复制后的文件属组权限
参数:mode---设置复制后的文件权限(600 755)

1.4.5file----文件属性修改/目录创建/文件创建

参数:owner---设置复制后的文件属主权限
参数:group---设置复制后的文件属组权限
参数:mode---设置复制后的文件权限(600 755)
ansible 172.16.1.41 -m file -a "dest=/tmp/file01.txt owner=oldboy group=oldboy mode=600"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "gid": 500, 
    "group": "oldboy", 
    "mode": "0600", 
    "owner": "oldboy", 
    "path": "/tmp/file01.txt", 
    "size": 6, 
    "state": "file", 
    "uid": 500
}

参数:state---用于指定创建目录或文件
创建文件
ansible 172.16.1.41 -m file -a "dest=/tmp/file01.txt state=touch"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "dest": "/tmp/file01.txt", 
    "gid": 0, 
    "group": "root", 
    "mode": "0644", 
    "owner": "root", 
    "size": 0, 
    "state": "file", 
    "uid": 0
}

创建目录:
ansible 172.16.1.41 -m file -a "dest=/tmp/dir01 state=directory"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "gid": 0, 
    "group": "root", 
    "mode": "0755", 
    "owner": "root", 
    "path": "/tmp/dir01", 
    "size": 4096, 
    "state": "directory", 
    "uid": 0
}

1.4.6包管理模块yum---安装软件包模块

name:执行要安装软件的名称,以及软件的版本
state:installed安装  absent(卸载)
ansible 172.16.1.41 -m yum -a "name=iftop state=installed"
ansible 172.16.1.41 -m yum -a "name=iftop state=absent"

list:指定软件名称,查看软件是否可以安装,以及是否已经安装过了
ansible 172.16.1.41 -m yum -a "list=iftop"

[root@m01 ~]# ansible 172.16.1.41 -m yum -a "name=iftop state=installed"
172.16.1.41 | SUCCESS => {
    "changed": false, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "iftop-1.0-0.14.pre4.el6.x86_64 providing iftop is already installed"
    ]
}
[root@m01 ~]# ansible 172.16.1.41 -m yum -a "name=iftop state=absent"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror, security\nSetting up Remove Process\nResolving Dependencies\n--> Running transaction check\n---> Package iftop.x86_64 0:1.0-0.14.pre4.el6 will be erased\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package        Arch            Version                    Repository      Size\n================================================================================\nRemoving:\n iftop          x86_64          1.0-0.14.pre4.el6          @epel           89 k\n\nTransaction Summary\n================================================================================\nRemove        1 Package(s)\n\nInstalled size: 89 k\nDownloading Packages:\nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r  Erasing    : iftop-1.0-0.14.pre4.el6.x86_64                               1/1 \n\r  Verifying  : iftop-1.0-0.14.pre4.el6.x86_64                               1/1 \n\nRemoved:\n  iftop.x86_64 0:1.0-0.14.pre4.el6                                              \n\nComplete!\n"
    ]
}
[root@m01 ~]# ansible 172.16.1.41 -m yum -a "name=iftop state=installed"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "msg": "", 
    "rc": 0, 
    "results": [
        "Loaded plugins: fastestmirror, security\nSetting up Install Process\nLoading mirror speeds from cached hostfile\n * base: mirrors.aliyun.com\n * extras: mirrors.aliyun.com\n * updates: mirrors.aliyun.com\nResolving Dependencies\n--> Running transaction check\n---> Package iftop.x86_64 0:1.0-0.14.pre4.el6 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package        Arch            Version                     Repository     Size\n================================================================================\nInstalling:\n iftop          x86_64          1.0-0.14.pre4.el6           epel           49 k\n\nTransaction Summary\n================================================================================\nInstall       1 Package(s)\n\nTotal download size: 49 k\nInstalled size: 89 k\nDownloading Packages:\nRunning rpm_check_debug\nRunning Transaction Test\nTransaction Test Succeeded\nRunning Transaction\n\r  Installing : iftop-1.0-0.14.pre4.el6.x86_64                               1/1 \n\r  Verifying  : iftop-1.0-0.14.pre4.el6.x86_64                               1/1 \n\nInstalled:\n  iftop.x86_64 0:1.0-0.14.pre4.el6                                              \n\nComplete!\n"
    ]
}
[root@m01 ~]# ansible 172.16.1.41 -m yum -a "list=iftop"
172.16.1.41 | SUCCESS => {
    "changed": false, 
    "results": [
        {
            "arch": "x86_64", 
            "envra": "0:iftop-1.0-0.14.pre4.el6.x86_64", 
            "epoch": "0", 
            "name": "iftop", 
            "release": "0.14.pre4.el6", 
            "repo": "epel", 
            "version": "1.0", 
            "yumstate": "available"
        }, 
        {
            "arch": "x86_64", 
            "envra": "0:iftop-1.0-0.14.pre4.el6.x86_64", 
            "epoch": "0", 
            "name": "iftop", 
            "release": "0.14.pre4.el6", 
            "repo": "installed", 
            "version": "1.0", 
            "yumstate": "installed"
        }
    ]
}
[root@m01 ~]# ansible 172.16.1.41 -m yum -a "list=ift"
172.16.1.41 | SUCCESS => {
    "changed": false, 
    "results": []
}
[root@m01 ~]# 

1.4.7系统模块service---管理服务状态模块

name: 指定要管理的服务名称(管理的服务一定在chkconfig中可以看到)
state:stopped started restarted reloaded
enabled:yes表示服务开机自启动 no表示服务开机不要自动启动

ansible 172.16.1.41 -m service -a "name=crond state=started enabled=yes"

[root@m01 ~]# ansible 172.16.1.41 -m service -a "name=crond state=stopped enabled=no"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "enabled": false, 
    "name": "crond", 
    "state": "stopped"
}
[root@m01 ~]# ansible 172.16.1.41 -m shell -a "chkconfig --list|grep crond"
172.16.1.41 | SUCCESS | rc=0 >>
crond           0:off   1:off   2:off   3:off   4:off   5:off   6:off

[root@m01 ~]# ansible 172.16.1.41 -m shell -a "service crond status"
172.16.1.41 | FAILED | rc=3 >>
crond is stoppednon-zero return code

[root@m01 ~]# ansible 172.16.1.41 -m service -a "name=crond state=started enabled=yes"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "enabled": true, 
    "name": "crond", 
    "state": "started"
}
[root@m01 ~]# ansible 172.16.1.41 -m shell -a "service crond status"
172.16.1.41 | SUCCESS | rc=0 >>
crond (pid  8420) is running...

[root@m01 ~]# ansible 172.16.1.41 -m shell -a "chkconfig --list|grep crond"
172.16.1.41 | SUCCESS | rc=0 >>
crond           0:off   1:off   2:on    3:on    4:on    5:on    6:off

[root@m01 ~]# 

1.4.8cron---定时任务模块

minute=0-59 * */n , -   hour  day  month weekday  job='/bin/sh /server/scripts/test.sh &>/dev/null'

添加定时任务
ansible 172.16.1.41 -m cron -a "minute=0 hour=0 job='/bin/sh /server/scripts/test.sh &>/dev/null'"
ansible 172.16.1.41 -m cron -a "name=oldboy02 minute=0 hour=0 job='/bin/sh /server/scripts/test.sh &>/dev/null'"

删除定时任务
ansible 172.16.1.41 -m cron -a "name=oldboy02 minute=0 hour=0 job='/bin/sh /server/scripts/test.sh &>/dev/null' state=absent"
ansible 172.16.1.41 -m cron -a "name=oldboy01 state=absent"

注释定时任务
ansible 172.16.1.41 -m cron -a "name=oldboy01 minute=0 hour=0 job='/bin/sh /server/scripts/test.sh &>/dev/null' disabled=yes"
ansible 172.16.1.41 -m cron -a "name=oldboy01 job='/bin/sh /server/scripts/test.sh &>/dev/null' disabled=no"

[root@m01 ~]# ansible 172.16.1.41 -m cron -a "name=oldboy01 minute=*/1 hour=* day=* month=* weekday=* job='/bin/sh  /server/scripts/sum.sh >dev/null 2>&1'"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "oldboy01"
    ]
}
[root@m01 ~]# ansible 172.16.1.41 -m shell -a "crontab -l"
172.16.1.41 | SUCCESS | rc=0 >>
#Ansible: oldboy01
*/1 * * * * /bin/sh  /server/scripts/sum.sh >dev/null 2>&1

[root@m01 ~]# ansible 172.16.1.41 -m cron -a "name=oldboy01 state=absent"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": []
}
[root@m01 ~]# ansible 172.16.1.41 -m shell -a "crontab -l"
172.16.1.41 | SUCCESS | rc=0 >>

[root@m01 ~]# ansible 172.16.1.41 -m cron -a "name=oldboy01 minute=*/1 hour=* day=* month=* weekday=* job='/bin/sh  /server/scripts/sum.sh >dev/null 2>&1'"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "oldboy01"
    ]
}
[root@m01 ~]# ansible 172.16.1.41 -m shell -a "crontab -l"
172.16.1.41 | SUCCESS | rc=0 >>
#Ansible: oldboy01
*/1 * * * * /bin/sh  /server/scripts/sum.sh >dev/null 2>&1

[root@m01 ~]# ansible 172.16.1.41 -m cron -a "name=oldboy01 disabled=yes"
172.16.1.41 | FAILED! => {
    "changed": false, 
    "msg": "You must specify 'job' to install a new cron job or variable"
}
[root@m01 ~]# ansible 172.16.1.41 -m cron -a "name=oldboy01 minute=*/1 hour=* day=* month=* weekday=* job='/bin/sh  /server/scripts/sum.sh >dev/null 2>&1' disabled=yes"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "oldboy01"
    ]
}
[root@m01 ~]# ansible 172.16.1.41 -m shell -a "crontab -l"
172.16.1.41 | SUCCESS | rc=0 >>
#Ansible: oldboy01
#*/1 * * * * /bin/sh  /server/scripts/sum.sh >dev/null 2>&1

[root@m01 ~]# ansible 172.16.1.41 -m cron -a "name=oldboy01 minute=*/1 hour=* day=* month=* weekday=* job='/bin/sh  /server/scripts/sum.sh >dev/null 2>&1' disabled=no"
172.16.1.41 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "oldboy01"
    ]
}
[root@m01 ~]# ansible 172.16.1.41 -m shell -a "crontab -l"
172.16.1.41 | SUCCESS | rc=0 >>
#Ansible: oldboy01
*/1 * * * * /bin/sh  /server/scripts/sum.sh >dev/null 2>&1

[root@m01 ~]# 

1.5command play-book

- hosts: 172.16.1.41
  tasks:
    - name: step01:install rsync
      yum: name=rsync state=installed
    - name: step02:edit rsync conf file
      copy: src=/etc/ansible/conf/rsync_conf/rsyncd.conf dest=/etc/
    - name: step03:create rsync user
      user: name=rsync state=present createhome=no shell=/sbin/nologin
    - name: step04:create auth file
      copy: src=/etc/ansible/conf/rsync_conf/rsync.password dest=/etc/ mode=600
    - name: step05:create backup dir
      file: dest=/backup state=directory owner=rsync group=rsync
    - name: step06:boot rsync server
      shell: rsync --daemon creates=/var/run/rsyncd.pid

- hosts: 172.16.1.31
  tasks:
    - name: step01:create auth file
      copy: src=/etc/ansible/conf/rsync_conf/rsync_client.password dest=/etc/rsync.password mode=600
执行脚本方法:
ansible-playbook /etc/ansible/ansible-playbook/test.yaml
模拟执行yaml
ansible-playbook -C /etc/ansible/ansible-playbook/test.yaml

1.5.1playbook的优势

首先,上面的操作也有自己的名字,叫adhoc
1.playbook比adhoc功能更全
2.控制好依赖
3.展示直观
4.持久使用

12.ansible(1)_第1张图片

[root@m01 playbook]# ansible-playbook --list-hosts test.yml 

playbook: test.yml

  play #1 (nginx): nginx    TAGS: []
    pattern: [u'nginx']
    hosts (1):
      10.0.0.62

[root@m01 playbook]# ansible-playbook -i /etc/ansible/hosts  test.yml 

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
changed: [10.0.0.62]

PLAY RECAP ************************************************************************************************
10.0.0.62   

1.5.2yaml语法

大小写敏感
使用缩进表示层级关系(只能使用空格,不能使用tab)
yaml文件以"---"作为文档的开始

1.5.3支持的数据结构

纯数字,布尔,字符串
字典:{name:vita}
列表:
-apple
-orange

1.5.4playbook中的变量

1.5.4.1playbook的yaml文件中定义变量

[root@m01 playbook]# cat test,y
cat: test,y: No such file or directory
[root@m01 playbook]# cat test.yml 
- hosts: nginx
  vars:
    tl_dir: /server/tools
    ap_dir: /application
    an_conf: /etc/ansible/conf
  tasks:
    - name: mkdir -p /tomcat
      shell: echo {{tl_dir}}

[root@m01 playbook]# ansible-playbook test.yml 

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
changed: [10.0.0.62]

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=2    changed=1    unreachable=0    failed=0   

1.5.4.2--extra-vars执行参数赋给变量

[root@m01 playbook]# cat test.yml 
- hosts: nginx
  vars:
    tl_dir: /server/tools
    ap_dir: /application
    an_conf: /etc/ansible/conf
  tasks:
    - name: mkdir -p /tomcat
      shell: echo {{extra_var}}

[root@m01 playbook]# ansible-playbook test.yml --extra-vars "extra_var=hhhh"

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
changed: [10.0.0.62]

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=2    changed=1    unreachable=0    failed=0   

1.5.4.3hosts中定义变量

[root@m01 playbook]# cat /etc/ansible/hosts
10.0.0.61
[db]
172.16.1.61
[php]
172.16.1.61
[nginx]
10.0.0.62 ansible_ssh_user=root  ansible_ssh_pass=123456
[nginx:vars]
extra_var=hhhh

[root@m01 playbook]# 

[root@m01 playbook]# cat test.yml 
- hosts: nginx
  vars:
    tl_dir: /server/tools
    ap_dir: /application
    an_conf: /etc/ansible/conf
  tasks:
    - name: mkdir -p /tomcat
      shell: echo {{extra_var}}

[root@m01 playbook]# ansible-playbook test.yml

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
changed: [10.0.0.62]

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=2    changed=1    unreachable=0    failed=0   

1.5.4.4注册变量

[root@m01 playbook]# cat test.yml 
- hosts: nginx
  vars:
    tl_dir: /server/tools
    ap_dir: /application
    an_conf: /etc/ansible/conf
  tasks:
    - name: mkdir -p /tomcat
      command: date
      register: date_output
    - name: echo
      shell: echo {{date_output}}

[root@m01 playbook]# ansible-playbook test.yml 

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
changed: [10.0.0.62]

TASK [echo] ***********************************************************************************************
changed: [10.0.0.62]

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=3    changed=2    unreachable=0    failed=0  

1.5.5基本语句

1.5.5.1条件语句

[root@m01 playbook]# cat test.yml 
- hosts: nginx
  vars:
    tl_dir: /server/tools
    ap_dir: /application
    an_conf: /etc/ansible/conf
  tasks:
    - name: mkdir -p /tomcat
      command: touch /opt/{{ansible_distribution}}_system
      when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "7") or (ansible_distribution == "Debian" and ansible_distribution_major_version == "6")
[root@m01 playbook]# 

[root@m01 playbook]# ansible-playbook test.yml 

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
 [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.

changed: [10.0.0.62]

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=2    changed=1    unreachable=0    failed=0   

10.0.0.62是centos7,查看
[root@m02 opt]# ll
total 8
-rw-r--r-- 1 root root   0 Aug  1 21:50 CentOS_system

1.5.5.2循环语句

12.ansible(1)_第2张图片

1.字典循环--with_dict

[root@m01 playbook]# cat test.yml 
- hosts: nginx
  vars:
    tl_dir: /server/tools
    ap_dir: /application
    an_conf: /etc/ansible/conf
  tasks:
    - name: mkdir -p /tomcat
      debug: msg={{ item.key }}---{{item.value}}
      with_dict:
          {'name':'wheel', 'val':'wheel'}
[root@m01 playbook]# 

[root@m01 playbook]# ansible-playbook test.yml 

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
ok: [10.0.0.62] => (item={'value': u'wheel', 'key': u'name'}) => {
    "msg": "name---wheel"
}
ok: [10.0.0.62] => (item={'value': u'wheel', 'key': u'val'}) => {
    "msg": "val---wheel"
}

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=2    changed=0    unreachable=0    failed=0   
[root@m01 playbook]# cat test.yml 
- hosts: nginx
  vars:
    tl_dir: /server/tools
    ap_dir: /application
    an_conf: /etc/ansible/conf
  tasks:
    - name: mkdir -p /tomcat
      debug: msg={{ item.key }}---{{item.value}}
      with_dict:
          {'vita':{'english':60,'chinese':80}, 'lili':{'english':90,'chinese':80}}
      when: item.value.english>60

[root@m01 playbook]# ansible-playbook test.yml 

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
skipping: [10.0.0.62] => (item={'value': {u'chinese': 80, u'english': 60}, 'key': u'vita'}) 
ok: [10.0.0.62] => (item={'value': {u'chinese': 80, u'english': 90}, 'key': u'lili'}) => {
    "msg": "lili---{u'chinese': 80, u'english': 90}"
}

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=2    changed=0    unreachable=0    failed=0   

2、with_items


[root@m01 playbook]# cat test.yml 
- hosts: nginx
  vars:
    tl_dir: /server/tools
    ap_dir: /application
    an_conf: /etc/ansible/conf
  tasks:
    - name: mkdir -p /tomcat
      debug: msg={{ item.name }}---{{item.val}}
      with_items:
          -  {'name':'wheel', 'val':'wheel'}
          -  {'name':'wheel2', 'val':'wheel2'}
[root@m01 playbook]# 

[root@m01 playbook]# ansible-playbook test.yml 

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
ok: [10.0.0.62] => (item={u'name': u'wheel', u'val': u'wheel'}) => {
    "msg": "wheel---wheel"
}
ok: [10.0.0.62] => (item={u'name': u'wheel2', u'val': u'wheel2'}) => {
    "msg": "wheel2---wheel2"
}

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=2    changed=0    unreachable=0    failed=0   

3.文件循环

[root@m01 playbook]# cat test.yml 
- hosts: nginx
  vars:
    tl_dir: /server/tools
    ap_dir: /application
    an_conf: /etc/ansible/conf
  tasks:
    - name: mkdir -p /tomcat
      debug: msg={{ item }}
      with_fileglob:
          - /etc/ansible/*

[root@m01 playbook]# ansible-playbook test.yml 

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
ok: [10.0.0.62] => (item=/etc/ansible/hosts) => {
    "msg": "/etc/ansible/hosts"
}
ok: [10.0.0.62] => (item=/etc/ansible/hosts.rpmsave) => {
    "msg": "/etc/ansible/hosts.rpmsave"
}
ok: [10.0.0.62] => (item=/etc/ansible/ansible.cfg) => {
    "msg": "/etc/ansible/ansible.cfg"
}

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=2    changed=0    unreachable=0    failed=0   

1.5.6异常处理

1.5.6.1忽略错误

默认会检查命令和模块的返回状态,遇到错误就中断playbook的执行
加入参数:ignore_errors:yes
上面即使报错了,下面的任务也会进行

[root@m01 playbook]# cat test.yml 
- hosts: nginx
  vars:
    tl_dir: /server/tools
    ap_dir: /application
    an_conf: /etc/ansible/conf
  tasks:
    - name: mkdir -p /tomcat
      command: /bin/false
      ignore_errors: yes
    - name: debug
      debug: msg=
[root@m01 playbook]# 

[root@m01 playbook]# ansible-playbook test.yml 

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
fatal: [10.0.0.62]: FAILED! => {"changed": true, "cmd": ["/bin/false"], "delta": "0:00:00.002755", "end": "2019-08-01 22:26:32.949887", "msg": "non-zero return code", "rc": 1, "start": "2019-08-01 22:26:32.947132", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
...ignoring

TASK [debug] **********************************************************************************************
ok: [10.0.0.62] => {
    "msg": "" #仍然输出了msg
}

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=3    changed=1    unreachable=0    failed=0   
#注释掉ignore_errors
#msg就没有输出了
[root@m01 playbook]# ansible-playbook test.yml 

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
fatal: [10.0.0.62]: FAILED! => {"changed": true, "cmd": ["/bin/false"], "delta": "0:00:00.001739", "end": "2019-08-01 22:27:48.758480", "msg": "non-zero return code", "rc": 1, "start": "2019-08-01 22:27:48.756741", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}
    to retry, use: --limit @/etc/ansible/playbook/test.retry

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=1    changed=0    unreachable=0    failed=1   

[root@m01 playbook]# 

1.5.6.2faild_when

#当进程数大于3的时候,后面的命令就不执行了
[root@m01 playbook]# cat test.yml 
- hosts: nginx
  vars:
    tl_dir: /server/tools
    ap_dir: /application
    an_conf: /etc/ansible/conf
  tasks:
    - name: mkdir -p /tomcat
      shell: ps -ef|wc -l
      register: process_count
      failed_when: process_count > 3
    - name: debug
      debug: msg=

[root@m01 playbook]# ansible-playbook test.yml 

PLAY [nginx] **********************************************************************************************

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

TASK [mkdir -p /tomcat] ***********************************************************************************
fatal: [10.0.0.62]: FAILED! => {"changed": true, "cmd": "ps -ef|wc -l", "delta": "0:00:00.017159", "end": "2019-08-01 22:33:52.220817", "failed_when_result": true, "rc": 0, "start": "2019-08-01 22:33:52.203658", "stderr": "", "stderr_lines": [], "stdout": "116", "stdout_lines": ["116"]}
    to retry, use: --limit @/etc/ansible/playbook/test.retry

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=1    changed=0    unreachable=0    failed=1   

1.5.7标签

通过tags和任务对象进行捆绑,控制部分或指定的task执行
-t:执行指定的tag标签任务
--skip-tags:执行指定的标签之外的任务
[root@m01 playbook]# cat test.yml 
- hosts: nginx
  vars:
    tl_dir: /server/tools
    ap_dir: /application
    an_conf: /etc/ansible/conf
  tasks:
      - name: msg = "cfile1-cfile3"
        shell: echo "cfile1-cfile3">/opt/cfile1
        tags:
            - cfile1
            - cfile3
      - name: msg = "cfile2"
        shell: echo "cfile2">/opt/cfile2
        tags:
            - cfile2
[root@m01 playbook]# 

[root@m01 playbook]# ansible-playbook test.yml -t cfile1

PLAY [nginx] **********************************************************************************************

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

TASK [msg = "cfile1-cfile3"] ******************************************************************************
changed: [10.0.0.62]

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=2    changed=1    unreachable=0    failed=0   

[root@m02 opt]# cat cfile1 
cfile1-cfile3
62上吧刚刚创建的文件删除
[root@m02 opt]# rm -rf cfile1 
[root@m02 opt]# ll

[root@m02 opt]# 

[root@m01 playbook]# ansible-playbook test.yml --skip-tags cfile2

PLAY [nginx] **********************************************************************************************

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

TASK [msg = "cfile1-cfile3"] ******************************************************************************
changed: [10.0.0.62]

PLAY RECAP ************************************************************************************************
10.0.0.62                  : ok=2    changed=1    unreachable=0    failed=0   

[root@m01 playbook]# 

62上再次查看
[root@m02 opt]# cat cfile1 
cfile1-cfile3

1.6ansible实现互相的免密码

**管理机:**
172.16.1.61

**被管理机:**
172.16.1.31
172.16.1.41
172.16.1.7

***下面是在管理机61上进行操作***
**管理机和被管理机都要安装sshpass**
[root@m01 ansible]#yum install -y sshpass
[root@m01 ansible]# ansible oldboy -m yum -a "name=sshpass"

**管理机上首先执行fenfa_key.sh实现管理机对其他主机的免密码登录,并执行fenfa_chek.sh进行验证:**
[root@m01 scripts]# cat fenfa_key.sh 
#!/bin/bash
#description:back file to the directory of /backup
#author:vita
#time:2019-03-04
rm -rf /root/.ssh/id_dsa
ssh-keygen -f /root/.ssh/id_dsa -N ""
for ip in 31 41 7 61
do
    sshpass -p123456 ssh-copy-id -i /root/.ssh/id_dsa.pub "-o StrictHostKeyChecking=no 172.16.1.$ip"
done
[root@m01 scripts]# 

[root@m01 scripts]# cat fenfa_check.sh 
#!/bin/bash
#description:back file to the directory of /backup
#author:vita
#time:2019-03-04
[ $# -ne 1 ]&&echo "you should use this script like sh fenfa_check.sh pwd"&&exit
for ip in 31 41 7 61
do
    echo "start to excute 172.16.1.$ip"
    ssh 172.16.1.$ip $1
    echo "172.16.1.$ip end"
done

**管理机上执行上面脚本**
[root@m01 ansible]#sh /server/scripts/fenfa_key.sh
[root@m01 ansible]#sh /server/scripts/fenfa_check.sh pwd

**被管理机上执行脚本**
[root@m01 ansible]# ansible oldboy -m script -a "/server/scripts/fenfa_key.sh"
[root@m01 scripts]# ansible oldboy -m script -a "/server/scripts/fenfa_check.sh pwd"

验证成功,即可互相通信