diff --git a/ansible/Ansible-jinja2模板.md b/ansible/Ansible-jinja2模板.md
new file mode 100644
index 0000000..692539c
--- /dev/null
+++ b/ansible/Ansible-jinja2模板.md
@@ -0,0 +1,142 @@
+
Ansible-jinja2模板
+
+------
+
+**作者:行癫(盗版必究)**
+
+## 一:简介
+
+ ansible通常使用jinja2模板来修改被管理主机的配置文件
+
+ 使用ansible的jinja2模板,也就是template模块,该模块和copy模块一样,都是将文件复制到远端主机上;区别在于template模块可以获取要复制的文件中变量的值;而copy则是原封不动的把文件内容复制过去,比如针对不同的主机定义不同的变量,template会在将配置文件分发出去之前读取变量到jinja2模板,然后分发到不通的被管理主机上
+
+ ansible允许jinja2模板中使用条件判断和循环,但是jinja2判断循环语法不允许在playbook中使用
+
+ jinja2 文件件以 .j2 为后缀, 也可以不写后缀
+
+## 二:基本使用
+
+#### 1.模板基本语法
+
+ 要在配置文件中使用jinja2,playbook中的tasks必须使用template模块
+
+ 模板配置文件里面使用变量,比如{{ port }}或者使用{{ facts变量 }}
+
+#### 2.模板逻辑关系
+
+```jinja
+{% for i in EXPR %}...{% endfor %}作为循环表达式
+
+{% if EXPR %}...{% elif EXPR %}...{% endif %}作为条件判断
+
+{# COMMENT #}表示注释
+```
+
+## 三:使用案例
+
+#### 1.案例一
+
+ 使用facts变量
+
+```yaml
+[root@db2 memcache]# cat jinja1.yaml
+- hosts: all
+ tasks:
+ - name: copy template file /etc/motd
+ template: src=./motd.j2 dest=/etc/motd backup=yes
+
+[root@db2 memcache]# cat motd.j2
+Welcome to qingcheng service!!
+This System Hostname: {{ ansible_hostname }}
+This System total memory is: {{ ansible_memtotal_mb }} MB
+This System free memory is: {{ ansible_memfree_mb }} MB
+```
+
+#### 2.案例二
+
+ nginx负载均衡变量
+
+```yaml
+[root@db2 memcache]# cat kod_proxy.conf.j2
+upstream {{ server_name }} {
+ {% for i in range(1,10) %}
+ server 192.168.10.{{ i }};
+ {% endfor %}
+}
+server {
+ listen {{ http_port }};
+ server_name {{ server_name }};
+ location / {
+ proxy_pass http://{{ server_name }};
+ include proxy_params;
+ }
+}
+[root@db2 memcache]# cat jinja2.yaml
+- hosts: webserver
+ vars:
+ - http_port: 80
+ - server_name: kod_qingchen.com
+ tasks:
+ - name: install nginx server
+ yum: name=nginx state=latest
+ - name: configure nginx virt
+ template: src=./kod_proxy.conf.j2 dest=/etc/nginx/conf.d/proxy_kod.conf
+ notify: Restart Nginx Server
+ - name: start nginx server
+ service: name=nginx state=started enabled=yes
+ handlers:
+ - name: Restart Nginx Server
+ service: name=nginx state=restarted
+```
+
+#### 3.案例三
+
+ keepalive主从
+
+```shell
+inventory中的host_vars根据不同主机设定不同的变量
+在playbook中是when判断主机名称,然后分发不同的配置文件
+使用jinja2的方式渲染出不同的配置文件
+```
+
+```jinja2
+[root@db2 memcache]# cat keepalived.yaml
+- hosts: all
+ tasks:
+ - name: copy template keepalived configure
+ template: src=keepalived.j2 dest=/etc/keepalived/keepalived.conf
+ notify: Restart keepalived service
+ handler:
+ - name: Restart keepalived service
+ service: name=keepalived state=restarted
+
+[root@db2 memcache]# cat keepalived.j2
+global_defs {
+ router_id {{ ansible_fqdn }}
+}
+
+vrrp_instance VI_1 {
+{% if ansible_fqdn == "web01" %}
+ state MASTER
+ priority 150
+{% elif ansible_fqdn == "web02" %}
+ state BACKUP
+ priority 100
+{% endif %}
+ interface eth0
+ virtual_router_id 50
+ advert_int 1
+ authentication {
+ auth_type PASS
+ auth_pass 1111
+ }
+ virtual_ipaddress {
+ 10.0.0.3
+ }
+}
+```
+
+
+
+
+
diff --git a/ansible/Ansible之Setup模块.md b/ansible/Ansible之Setup模块.md
new file mode 100644
index 0000000..791d340
--- /dev/null
+++ b/ansible/Ansible之Setup模块.md
@@ -0,0 +1,740 @@
+Ansible之Setup模块
+
+------
+
+**作者:行癫(盗版必究)**
+
+## 一:所有参数
+
+```yml
+10.0.0.111 | SUCCESS => {
+ "ansible_facts": {
+ "ansible_all_ipv4_addresses": [
+ "10.0.0.111"
+ ],
+ "ansible_all_ipv6_addresses": [
+ "fe80::a1d7:aadb:3ae3:bbb9"
+ ],
+ "ansible_apparmor": {
+ "status": "disabled"
+ },
+ "ansible_architecture": "x86_64",
+ "ansible_bios_date": "11/12/2020",
+ "ansible_bios_version": "6.00",
+ "ansible_cmdline": {
+ "BOOT_IMAGE": "/vmlinuz-3.10.0-693.el7.x86_64",
+ "LANG": "en_US.UTF-8",
+ "quiet": true,
+ "rd.lvm.lv": "centos/root",
+ "rhgb": true,
+ "ro": true,
+ "root": "/dev/mapper/centos-root"
+ },
+ "ansible_date_time": {
+ "date": "2023-03-02",
+ "day": "02",
+ "epoch": "1677768313",
+ "hour": "22",
+ "iso8601": "2023-03-02T14:45:13Z",
+ "iso8601_basic": "20230302T224513178165",
+ "iso8601_basic_short": "20230302T224513",
+ "iso8601_micro": "2023-03-02T14:45:13.178165Z",
+ "minute": "45",
+ "month": "03",
+ "second": "13",
+ "time": "22:45:13",
+ "tz": "CST",
+ "tz_offset": "+0800",
+ "weekday": "Thursday",
+ "weekday_number": "4",
+ "weeknumber": "09",
+ "year": "2023"
+ },
+ "ansible_default_ipv4": {
+ "address": "10.0.0.111",
+ "alias": "ens33",
+ "broadcast": "10.0.0.255",
+ "gateway": "10.0.0.2",
+ "interface": "ens33",
+ "macaddress": "00:0c:29:0d:1c:29",
+ "mtu": 1500,
+ "netmask": "255.255.255.0",
+ "network": "10.0.0.0",
+ "type": "ether"
+ },
+ "ansible_default_ipv6": {},
+ "ansible_device_links": {
+ "ids": {
+ "dm-0": [
+ "dm-name-centos-root",
+ "dm-uuid-LVM-jtnKDeIbgg03hClVGR4QFsF0xdtxSolvn3Yfi9VBej4wXITukpJCMpFT914kP7cH"
+ ],
+ "sda2": [
+ "lvm-pv-uuid-vWNEKk-udkQ-vl1K-YJck-9KMY-D13P-eAoAnR"
+ ],
+ "sr0": [
+ "ata-VMware_Virtual_IDE_CDROM_Drive_10000000000000000001"
+ ]
+ },
+ "labels": {
+ "sr0": [
+ "CentOS\\x207\\x20x86_64"
+ ]
+ },
+ "masters": {
+ "sda2": [
+ "dm-0"
+ ]
+ },
+ "uuids": {
+ "dm-0": [
+ "d0261be2-3486-4ff1-8563-8360393cfeb4"
+ ],
+ "sda1": [
+ "bdfa051f-b5a8-4713-9bee-440b49233372"
+ ],
+ "sr0": [
+ "2017-09-05-14-14-50-00"
+ ]
+ }
+ },
+ "ansible_devices": {
+ "dm-0": {
+ "holders": [],
+ "host": "",
+ "links": {
+ "ids": [
+ "dm-name-centos-root",
+ "dm-uuid-LVM-jtnKDeIbgg03hClVGR4QFsF0xdtxSolvn3Yfi9VBej4wXITukpJCMpFT914kP7cH"
+ ],
+ "labels": [],
+ "masters": [],
+ "uuids": [
+ "d0261be2-3486-4ff1-8563-8360393cfeb4"
+ ]
+ },
+ "model": null,
+ "partitions": {},
+ "removable": "0",
+ "rotational": "1",
+ "sas_address": null,
+ "sas_device_handle": null,
+ "scheduler_mode": "",
+ "sectors": "82853888",
+ "sectorsize": "512",
+ "size": "39.51 GB",
+ "support_discard": "0",
+ "vendor": null,
+ "virtual": 1
+ },
+ "sda": {
+ "holders": [],
+ "host": "",
+ "links": {
+ "ids": [],
+ "labels": [],
+ "masters": [],
+ "uuids": []
+ },
+ "model": "VMware Virtual S",
+ "partitions": {
+ "sda1": {
+ "holders": [],
+ "links": {
+ "ids": [],
+ "labels": [],
+ "masters": [],
+ "uuids": [
+ "bdfa051f-b5a8-4713-9bee-440b49233372"
+ ]
+ },
+ "sectors": "1024000",
+ "sectorsize": 512,
+ "size": "500.00 MB",
+ "start": "2048",
+ "uuid": "bdfa051f-b5a8-4713-9bee-440b49233372"
+ },
+ "sda2": {
+ "holders": [
+ "centos-root"
+ ],
+ "links": {
+ "ids": [
+ "lvm-pv-uuid-vWNEKk-udkQ-vl1K-YJck-9KMY-D13P-eAoAnR"
+ ],
+ "labels": [],
+ "masters": [
+ "dm-0"
+ ],
+ "uuids": []
+ },
+ "sectors": "82860032",
+ "sectorsize": 512,
+ "size": "39.51 GB",
+ "start": "1026048",
+ "uuid": null
+ }
+ },
+ "removable": "0",
+ "rotational": "1",
+ "sas_address": null,
+ "sas_device_handle": null,
+ "scheduler_mode": "deadline",
+ "sectors": "83886080",
+ "sectorsize": "512",
+ "size": "40.00 GB",
+ "support_discard": "0",
+ "vendor": "VMware,",
+ "virtual": 1
+ },
+ "sr0": {
+ "holders": [],
+ "host": "",
+ "links": {
+ "ids": [
+ "ata-VMware_Virtual_IDE_CDROM_Drive_10000000000000000001"
+ ],
+ "labels": [
+ "CentOS\\x207\\x20x86_64"
+ ],
+ "masters": [],
+ "uuids": [
+ "2017-09-05-14-14-50-00"
+ ]
+ },
+ "model": "VMware IDE CDR10",
+ "partitions": {},
+ "removable": "1",
+ "rotational": "1",
+ "sas_address": null,
+ "sas_device_handle": null,
+ "scheduler_mode": "cfq",
+ "sectors": "1622016",
+ "sectorsize": "2048",
+ "size": "792.00 MB",
+ "support_discard": "0",
+ "vendor": "NECVMWar",
+ "virtual": 1
+ }
+ },
+ "ansible_distribution": "CentOS",
+ "ansible_distribution_file_parsed": true,
+ "ansible_distribution_file_path": "/etc/redhat-release",
+ "ansible_distribution_file_variety": "RedHat",
+ "ansible_distribution_major_version": "7",
+ "ansible_distribution_release": "Core",
+ "ansible_distribution_version": "7.4",
+ "ansible_dns": {
+ "nameservers": [
+ "10.0.0.2"
+ ],
+ "search": [
+ "localdomain"
+ ]
+ },
+ "ansible_domain": "",
+ "ansible_effective_group_id": 0,
+ "ansible_effective_user_id": 0,
+ "ansible_ens33": {
+ "active": true,
+ "device": "ens33",
+ "features": {
+ "busy_poll": "off [fixed]",
+ "fcoe_mtu": "off [fixed]",
+ "generic_receive_offload": "on",
+ "generic_segmentation_offload": "on",
+ "highdma": "off [fixed]",
+ "hw_tc_offload": "off [fixed]",
+ "l2_fwd_offload": "off [fixed]",
+ "large_receive_offload": "off [fixed]",
+ "loopback": "off [fixed]",
+ "netns_local": "off [fixed]",
+ "ntuple_filters": "off [fixed]",
+ "receive_hashing": "off [fixed]",
+ "rx_all": "off",
+ "rx_checksumming": "off",
+ "rx_fcs": "off",
+ "rx_vlan_filter": "on [fixed]",
+ "rx_vlan_offload": "on",
+ "rx_vlan_stag_filter": "off [fixed]",
+ "rx_vlan_stag_hw_parse": "off [fixed]",
+ "scatter_gather": "on",
+ "tcp_segmentation_offload": "on",
+ "tx_checksum_fcoe_crc": "off [fixed]",
+ "tx_checksum_ip_generic": "on",
+ "tx_checksum_ipv4": "off [fixed]",
+ "tx_checksum_ipv6": "off [fixed]",
+ "tx_checksum_sctp": "off [fixed]",
+ "tx_checksumming": "on",
+ "tx_fcoe_segmentation": "off [fixed]",
+ "tx_gre_csum_segmentation": "off [fixed]",
+ "tx_gre_segmentation": "off [fixed]",
+ "tx_gso_partial": "off [fixed]",
+ "tx_gso_robust": "off [fixed]",
+ "tx_ipip_segmentation": "off [fixed]",
+ "tx_lockless": "off [fixed]",
+ "tx_mpls_segmentation": "off [fixed]",
+ "tx_nocache_copy": "off",
+ "tx_scatter_gather": "on",
+ "tx_scatter_gather_fraglist": "off [fixed]",
+ "tx_sctp_segmentation": "off [fixed]",
+ "tx_sit_segmentation": "off [fixed]",
+ "tx_tcp6_segmentation": "off [fixed]",
+ "tx_tcp_ecn_segmentation": "off [fixed]",
+ "tx_tcp_mangleid_segmentation": "off",
+ "tx_tcp_segmentation": "on",
+ "tx_udp_tnl_csum_segmentation": "off [fixed]",
+ "tx_udp_tnl_segmentation": "off [fixed]",
+ "tx_vlan_offload": "on [fixed]",
+ "tx_vlan_stag_hw_insert": "off [fixed]",
+ "udp_fragmentation_offload": "off [fixed]",
+ "vlan_challenged": "off [fixed]"
+ },
+ "hw_timestamp_filters": [],
+ "ipv4": {
+ "address": "10.0.0.111",
+ "broadcast": "10.0.0.255",
+ "netmask": "255.255.255.0",
+ "network": "10.0.0.0"
+ },
+ "ipv6": [
+ {
+ "address": "fe80::a1d7:aadb:3ae3:bbb9",
+ "prefix": "64",
+ "scope": "link"
+ }
+ ],
+ "macaddress": "00:0c:29:0d:1c:29",
+ "module": "e1000",
+ "mtu": 1500,
+ "pciid": "0000:02:01.0",
+ "promisc": false,
+ "speed": 1000,
+ "timestamping": [
+ "tx_software",
+ "rx_software",
+ "software"
+ ],
+ "type": "ether"
+ },
+ "ansible_env": {
+ "HOME": "/root",
+ "LANG": "en_US.UTF-8",
+ "LESSOPEN": "||/usr/bin/lesspipe.sh %s",
+ "LOGNAME": "root",
+ "LS_COLORS": "rs=0:di=38;5;27:ln=38;5;51:mh=44;38;5;15:pi=40;38;5;11:so=38;5;13:do=38;5;5:bd=48;5;232;38;5;11:cd=48;5;232;38;5;3:or=48;5;232;38;5;9:mi=05;48;5;232;38;5;15:su=48;5;196;38;5;15:sg=48;5;11;38;5;16:ca=48;5;196;38;5;226:tw=48;5;10;38;5;16:ow=48;5;10;38;5;21:st=48;5;21;38;5;15:ex=38;5;34:*.tar=38;5;9:*.tgz=38;5;9:*.arc=38;5;9:*.arj=38;5;9:*.taz=38;5;9:*.lha=38;5;9:*.lz4=38;5;9:*.lzh=38;5;9:*.lzma=38;5;9:*.tlz=38;5;9:*.txz=38;5;9:*.tzo=38;5;9:*.t7z=38;5;9:*.zip=38;5;9:*.z=38;5;9:*.Z=38;5;9:*.dz=38;5;9:*.gz=38;5;9:*.lrz=38;5;9:*.lz=38;5;9:*.lzo=38;5;9:*.xz=38;5;9:*.bz2=38;5;9:*.bz=38;5;9:*.tbz=38;5;9:*.tbz2=38;5;9:*.tz=38;5;9:*.deb=38;5;9:*.rpm=38;5;9:*.jar=38;5;9:*.war=38;5;9:*.ear=38;5;9:*.sar=38;5;9:*.rar=38;5;9:*.alz=38;5;9:*.ace=38;5;9:*.zoo=38;5;9:*.cpio=38;5;9:*.7z=38;5;9:*.rz=38;5;9:*.cab=38;5;9:*.jpg=38;5;13:*.jpeg=38;5;13:*.gif=38;5;13:*.bmp=38;5;13:*.pbm=38;5;13:*.pgm=38;5;13:*.ppm=38;5;13:*.tga=38;5;13:*.xbm=38;5;13:*.xpm=38;5;13:*.tif=38;5;13:*.tiff=38;5;13:*.png=38;5;13:*.svg=38;5;13:*.svgz=38;5;13:*.mng=38;5;13:*.pcx=38;5;13:*.mov=38;5;13:*.mpg=38;5;13:*.mpeg=38;5;13:*.m2v=38;5;13:*.mkv=38;5;13:*.webm=38;5;13:*.ogm=38;5;13:*.mp4=38;5;13:*.m4v=38;5;13:*.mp4v=38;5;13:*.vob=38;5;13:*.qt=38;5;13:*.nuv=38;5;13:*.wmv=38;5;13:*.asf=38;5;13:*.rm=38;5;13:*.rmvb=38;5;13:*.flc=38;5;13:*.avi=38;5;13:*.fli=38;5;13:*.flv=38;5;13:*.gl=38;5;13:*.dl=38;5;13:*.xcf=38;5;13:*.xwd=38;5;13:*.yuv=38;5;13:*.cgm=38;5;13:*.emf=38;5;13:*.axv=38;5;13:*.anx=38;5;13:*.ogv=38;5;13:*.ogx=38;5;13:*.aac=38;5;45:*.au=38;5;45:*.flac=38;5;45:*.mid=38;5;45:*.midi=38;5;45:*.mka=38;5;45:*.mp3=38;5;45:*.mpc=38;5;45:*.ogg=38;5;45:*.ra=38;5;45:*.wav=38;5;45:*.axa=38;5;45:*.oga=38;5;45:*.spx=38;5;45:*.xspf=38;5;45:",
+ "MAIL": "/var/mail/root",
+ "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
+ "PWD": "/root",
+ "SHELL": "/bin/bash",
+ "SHLVL": "2",
+ "SSH_CLIENT": "10.0.0.110 51406 22",
+ "SSH_CONNECTION": "10.0.0.110 51406 10.0.0.111 22",
+ "SSH_TTY": "/dev/pts/1",
+ "TERM": "xterm-256color",
+ "USER": "root",
+ "XDG_RUNTIME_DIR": "/run/user/0",
+ "XDG_SESSION_ID": "15",
+ "_": "/usr/bin/python"
+ },
+ "ansible_fibre_channel_wwn": [],
+ "ansible_fips": false,
+ "ansible_form_factor": "Other",
+ "ansible_fqdn": "xingdian",
+ "ansible_hostname": "xingdian",
+ "ansible_hostnqn": "",
+ "ansible_interfaces": [
+ "lo",
+ "ens33"
+ ],
+ "ansible_is_chroot": false,
+ "ansible_iscsi_iqn": "",
+ "ansible_kernel": "3.10.0-693.el7.x86_64",
+ "ansible_kernel_version": "#1 SMP Tue Aug 22 21:09:27 UTC 2017",
+ "ansible_lo": {
+ "active": true,
+ "device": "lo",
+ "features": {
+ "busy_poll": "off [fixed]",
+ "fcoe_mtu": "off [fixed]",
+ "generic_receive_offload": "on",
+ "generic_segmentation_offload": "on",
+ "highdma": "on [fixed]",
+ "hw_tc_offload": "off [fixed]",
+ "l2_fwd_offload": "off [fixed]",
+ "large_receive_offload": "off [fixed]",
+ "loopback": "on [fixed]",
+ "netns_local": "on [fixed]",
+ "ntuple_filters": "off [fixed]",
+ "receive_hashing": "off [fixed]",
+ "rx_all": "off [fixed]",
+ "rx_checksumming": "on [fixed]",
+ "rx_fcs": "off [fixed]",
+ "rx_vlan_filter": "off [fixed]",
+ "rx_vlan_offload": "off [fixed]",
+ "rx_vlan_stag_filter": "off [fixed]",
+ "rx_vlan_stag_hw_parse": "off [fixed]",
+ "scatter_gather": "on",
+ "tcp_segmentation_offload": "on",
+ "tx_checksum_fcoe_crc": "off [fixed]",
+ "tx_checksum_ip_generic": "on [fixed]",
+ "tx_checksum_ipv4": "off [fixed]",
+ "tx_checksum_ipv6": "off [fixed]",
+ "tx_checksum_sctp": "on [fixed]",
+ "tx_checksumming": "on",
+ "tx_fcoe_segmentation": "off [fixed]",
+ "tx_gre_csum_segmentation": "off [fixed]",
+ "tx_gre_segmentation": "off [fixed]",
+ "tx_gso_partial": "off [fixed]",
+ "tx_gso_robust": "off [fixed]",
+ "tx_ipip_segmentation": "off [fixed]",
+ "tx_lockless": "on [fixed]",
+ "tx_mpls_segmentation": "off [fixed]",
+ "tx_nocache_copy": "off [fixed]",
+ "tx_scatter_gather": "on [fixed]",
+ "tx_scatter_gather_fraglist": "on [fixed]",
+ "tx_sctp_segmentation": "on",
+ "tx_sit_segmentation": "off [fixed]",
+ "tx_tcp6_segmentation": "on",
+ "tx_tcp_ecn_segmentation": "on",
+ "tx_tcp_mangleid_segmentation": "on",
+ "tx_tcp_segmentation": "on",
+ "tx_udp_tnl_csum_segmentation": "off [fixed]",
+ "tx_udp_tnl_segmentation": "off [fixed]",
+ "tx_vlan_offload": "off [fixed]",
+ "tx_vlan_stag_hw_insert": "off [fixed]",
+ "udp_fragmentation_offload": "on",
+ "vlan_challenged": "on [fixed]"
+ },
+ "hw_timestamp_filters": [],
+ "ipv4": {
+ "address": "127.0.0.1",
+ "broadcast": "",
+ "netmask": "255.0.0.0",
+ "network": "127.0.0.0"
+ },
+ "ipv6": [
+ {
+ "address": "::1",
+ "prefix": "128",
+ "scope": "host"
+ }
+ ],
+ "mtu": 65536,
+ "promisc": false,
+ "timestamping": [
+ "rx_software",
+ "software"
+ ],
+ "type": "loopback"
+ },
+ "ansible_local": {},
+ "ansible_lsb": {},
+ "ansible_lvm": {
+ "lvs": {
+ "root": {
+ "size_g": "39.51",
+ "vg": "centos"
+ }
+ },
+ "pvs": {
+ "/dev/sda2": {
+ "free_g": "0",
+ "size_g": "39.51",
+ "vg": "centos"
+ }
+ },
+ "vgs": {
+ "centos": {
+ "free_g": "0",
+ "num_lvs": "1",
+ "num_pvs": "1",
+ "size_g": "39.51"
+ }
+ }
+ },
+ "ansible_machine": "x86_64",
+ "ansible_machine_id": "b2553b2f1ad64a88a81a775b55de0eb3",
+ "ansible_memfree_mb": 1754,
+ "ansible_memory_mb": {
+ "nocache": {
+ "free": 1833,
+ "used": 151
+ },
+ "real": {
+ "free": 1754,
+ "total": 1984,
+ "used": 230
+ },
+ "swap": {
+ "cached": 0,
+ "free": 0,
+ "total": 0,
+ "used": 0
+ }
+ },
+ "ansible_memtotal_mb": 1984,
+ "ansible_mounts": [
+ {
+ "block_available": 97092,
+ "block_size": 4096,
+ "block_total": 127145,
+ "block_used": 30053,
+ "device": "/dev/sda1",
+ "fstype": "xfs",
+ "inode_available": 255673,
+ "inode_total": 256000,
+ "inode_used": 327,
+ "mount": "/boot",
+ "options": "rw,relatime,attr2,inode64,noquota",
+ "size_available": 397688832,
+ "size_total": 520785920,
+ "uuid": "bdfa051f-b5a8-4713-9bee-440b49233372"
+ },
+ {
+ "block_available": 9998628,
+ "block_size": 4096,
+ "block_total": 10351679,
+ "block_used": 353051,
+ "device": "/dev/mapper/centos-root",
+ "fstype": "xfs",
+ "inode_available": 20687486,
+ "inode_total": 20713472,
+ "inode_used": 25986,
+ "mount": "/",
+ "options": "rw,relatime,attr2,inode64,noquota",
+ "size_available": 40954380288,
+ "size_total": 42400477184,
+ "uuid": "d0261be2-3486-4ff1-8563-8360393cfeb4"
+ }
+ ],
+ "ansible_nodename": "xingdian",
+ "ansible_os_family": "RedHat",
+ "ansible_pkg_mgr": "yum",
+ "ansible_proc_cmdline": {
+ "BOOT_IMAGE": "/vmlinuz-3.10.0-693.el7.x86_64",
+ "LANG": "en_US.UTF-8",
+ "quiet": true,
+ "rd.lvm.lv": "centos/root",
+ "rhgb": true,
+ "ro": true,
+ "root": "/dev/mapper/centos-root"
+ },
+ "ansible_processor": [
+ "0",
+ "GenuineIntel",
+ "11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz"
+ ],
+ "ansible_processor_cores": 1,
+ "ansible_processor_count": 1,
+ "ansible_processor_threads_per_core": 1,
+ "ansible_processor_vcpus": 1,
+ "ansible_product_name": "VMware Virtual Platform",
+ "ansible_product_serial": "VMware-56 4d 77 c3 38 eb b5 44-f9 c5 f5 a9 0c 0d 1c 29",
+ "ansible_product_uuid": "C3774D56-EB38-44B5-F9C5-F5A90C0D1C29",
+ "ansible_product_version": "None",
+ "ansible_python": {
+ "executable": "/usr/bin/python",
+ "has_sslcontext": true,
+ "type": "CPython",
+ "version": {
+ "major": 2,
+ "micro": 5,
+ "minor": 7,
+ "releaselevel": "final",
+ "serial": 0
+ },
+ "version_info": [
+ 2,
+ 7,
+ 5,
+ "final",
+ 0
+ ]
+ },
+ "ansible_python_version": "2.7.5",
+ "ansible_real_group_id": 0,
+ "ansible_real_user_id": 0,
+ "ansible_selinux": {
+ "status": "disabled"
+ },
+ "ansible_selinux_python_present": true,
+ "ansible_service_mgr": "systemd",
+ "ansible_ssh_host_key_ecdsa_public": "AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFWlYnYAyylfiZr2C9xiHsT8i2ao+RY8CY+z6wJEBQxdtg+/VHmxYOejdPKrq94IjLU00x5Iu096aQ5XdNyDUs4=",
+ "ansible_ssh_host_key_ed25519_public": "AAAAC3NzaC1lZDI1NTE5AAAAIPHn7/QapryKV1IenlFdQngIQed+y9YyziwtVYnBflG9",
+ "ansible_ssh_host_key_rsa_public": "AAAAB3NzaC1yc2EAAAADAQABAAABAQCso6OpQ9TsQ/2ihnVLtUpqK4y1hjR9WyHqKQFcqH7TN9TDxuyB+gPfN1IzC25IoUb8mp9zIiLNqg8epsNbKFj9l3WQUtx3fcSXqIcZdWeTWkltxz0DxSr0xQd+odYwQ+ppH5gFjvTnJNcVJhqfMLAdQjLFjSrZfvF28qUyTGj8HJC7qGneM9ECLQwQ+ZQ6qvjaXMpgUR4p9JsOdSeicGD3mZwIsvScfhHq011V/2ZCQAgCuUlO/Z6+Xbzc27ZPyu4wkZYWM+DyZEXi0cvO5WYV+tst8uwdBQhSaQi8T5Vu7eUitdoFBC9vTFjZiR39dxEHy2nlkTnJWZ9ChLY08iLf",
+ "ansible_swapfree_mb": 0,
+ "ansible_swaptotal_mb": 0,
+ "ansible_system": "Linux",
+ "ansible_system_capabilities": [
+ "cap_chown",
+ "cap_dac_override",
+ "cap_dac_read_search",
+ "cap_fowner",
+ "cap_fsetid",
+ "cap_kill",
+ "cap_setgid",
+ "cap_setuid",
+ "cap_setpcap",
+ "cap_linux_immutable",
+ "cap_net_bind_service",
+ "cap_net_broadcast",
+ "cap_net_admin",
+ "cap_net_raw",
+ "cap_ipc_lock",
+ "cap_ipc_owner",
+ "cap_sys_module",
+ "cap_sys_rawio",
+ "cap_sys_chroot",
+ "cap_sys_ptrace",
+ "cap_sys_pacct",
+ "cap_sys_admin",
+ "cap_sys_boot",
+ "cap_sys_nice",
+ "cap_sys_resource",
+ "cap_sys_time",
+ "cap_sys_tty_config",
+ "cap_mknod",
+ "cap_lease",
+ "cap_audit_write",
+ "cap_audit_control",
+ "cap_setfcap",
+ "cap_mac_override",
+ "cap_mac_admin",
+ "cap_syslog",
+ "35",
+ "36+ep"
+ ],
+ "ansible_system_capabilities_enforced": "True",
+ "ansible_system_vendor": "VMware, Inc.",
+ "ansible_uptime_seconds": 3024,
+ "ansible_user_dir": "/root",
+ "ansible_user_gecos": "root",
+ "ansible_user_gid": 0,
+ "ansible_user_id": "root",
+ "ansible_user_shell": "/bin/bash",
+ "ansible_user_uid": 0,
+ "ansible_userspace_architecture": "x86_64",
+ "ansible_userspace_bits": "64",
+ "ansible_virtualization_role": "guest",
+ "ansible_virtualization_type": "VMware",
+ "discovered_interpreter_python": "/usr/bin/python",
+ "gather_subset": [
+ "all"
+ ],
+ "module_setup": true
+ },
+ "changed": false
+}
+```
+
+## 二:使用Setup
+
+#### 1.案例一
+
+ 使用“ansible_fqdn”获取主机名称和域名
+
+```yml
+[root@xingdian ansible]# cat test.yml
+- name: test a playbook
+ hosts: web
+ tasks:
+ - name: hostname
+ debug:
+ msg: "{{ ansible_fqdn }}"
+```
+
+ 运行剧本
+
+```yaml
+[root@xingdian ansible]# ansible-playbook test.yml
+[WARNING]: Could not match supplied host pattern, ignoring: node1
+
+PLAY [test a playbook] ****************************************************************************************************************************************
+skipping: no hosts matched
+
+PLAY RECAP ****************************************************************************************************************************************************
+
+[root@xingdian ansible]# vim test.yml
+[root@xingdian ansible]# ansible-playbook test.yml
+
+PLAY [test a playbook] ****************************************************************************************************************************************
+
+TASK [Gathering Facts] ****************************************************************************************************************************************
+ok: [10.0.0.111]
+
+TASK [hostname] ***********************************************************************************************************************************************
+ok: [10.0.0.111] => {
+ "msg": "xingdian"
+}
+
+PLAY RECAP ****************************************************************************************************************************************************
+10.0.0.111 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
+```
+
+#### 2.案例二
+
+ 使用“ansible_ens33.ipv4.address”获取指定网卡IP地址
+
+```yaml
+[root@xingdian ansible]# cat test.yml
+- name: test a playbook
+ hosts: web
+ tasks:
+ - name: hostname
+ debug:
+ msg: "{{ ansible_ens33.ipv4.address }}"
+```
+
+ 运行剧本
+
+```yaml
+[root@xingdian ansible]# ansible-playbook test.yml
+
+PLAY [test a playbook] ****************************************************************************************************************************************
+
+TASK [Gathering Facts] ****************************************************************************************************************************************
+ok: [10.0.0.111]
+
+TASK [hostname] ***********************************************************************************************************************************************
+ok: [10.0.0.111] => {
+ "msg": "10.0.0.111"
+}
+
+PLAY RECAP ****************************************************************************************************************************************************
+10.0.0.111 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
+```
+
+#### 3.案例三
+
+ 使用“ansible_devices.sda.partitions.sda2.size”获取磁盘容量
+
+```yaml
+[root@xingdian ansible]# cat test.yml
+- name: test a playbook
+ hosts: web
+ tasks:
+ - name: hostname
+ debug:
+ msg: "{{ ansible_devices.sda.partitions.sda2.size }}"
+```
+
+ 运行剧本
+
+```yaml
+[root@xingdian ansible]# ansible-playbook test.yml
+
+PLAY [test a playbook] ****************************************************************************************************************************************
+
+TASK [Gathering Facts] ****************************************************************************************************************************************
+ok: [10.0.0.111]
+
+TASK [hostname] ***********************************************************************************************************************************************
+ok: [10.0.0.111] => {
+ "msg": "39.51 GB"
+}
+
+PLAY RECAP ****************************************************************************************************************************************************
+10.0.0.111 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
+```
+
diff --git a/ansible/Ansible自动化运维基础.md b/ansible/Ansible自动化运维基础.md
new file mode 100644
index 0000000..47346de
--- /dev/null
+++ b/ansible/Ansible自动化运维基础.md
@@ -0,0 +1,1097 @@
+Ansible自动化运维基础
+
+------
+
+**作者:行癫(盗版必究)**
+
+## 一:简介
+
+#### 1.自动化运维工具对比
+
+ Puppet:基于 Ruby 开发,采用 C/S 架构,扩展性强,基于 SSL,远程命令执行相对较弱
+
+ SaltStack:基于 Python 开发,采用 C/S 架构,YAML使得配置脚本更简单.需要配置客户端及服务器端;每台被控制节点需要安装agent
+
+ Ansible:基于 Python开发,分布式,无需客户端,轻量级,配置语法使用YAML语言,更强的远程命令执行操作
+
+#### 2.Ansible简介
+
+ ansible是新出现的自动化运维工具,基于Python开发,分布式,无需客户端,轻量级,实现了批量系统配置、批量程序部署、批量运行命令等功能,ansible是基于模块工作的,本身没有批量部署的能力。真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架
+
+特性:
+
+ no agents:不需要在被管控主机上安装任何客户端,更新时,只需在操作机上进行一次更新即可(不用安装客户端。分布式的)
+
+ no server:无服务器端,使用时直接运行命令即可
+
+ modules in any languages:基于模块工作,可使用任意语言开发模块
+
+ yaml,not code:使用yaml语言定制剧本playbook
+
+ ssh by default:基于SSH工作
+
+ strong multi-tier solution:可实现多级指挥
+
+特点:
+
+
+
+ connection plugins:连接插件,负责和被监控端实现通信,默认使用SSH连接
+
+ host inventory:主机清单,是一个配置文件里面定义监控的主机
+
+ modules : 模块,核心模块、command模块、自定义模块等
+
+ plugins : modules功能的补充,包括连接插件,邮件插件等
+
+ playbook:编排,定义 Ansible 多任务配置文件,非必需
+
+#### 3.部署Ansible
+
+环境准备:
+
+```shell
+环境:
+主机:4台 一个控制节点 3个被控制节点
+解析:本地互相解析(所有机器)
+# vim /etc/hosts
+192.168.1.10 ansible-web1
+192.168.1.11 ansible-web2
+192.168.1.12 ansible-web3
+192.168.1.9 ansible-server (控制节点服务器端)
+配置ssh公钥认证:控制节点需要发送ssh公钥给所有非被控制节点
+[root@ansible-server ~]# ssh-keygen
+[root@ansible-server ~]# ssh-copy-id -i 192.168.1.10 #所有机器
+
+所有机器:
+systemctl stop firewalld && setenforce 0
+```
+
+安装ansible:
+
+```shell
+安装:控制节点
+ 1. 配置EPEL网络yum源
+ [root@ansible-server ~]# yum install -y epel-release
+ 2. 安装ansible
+ [root@ansible-server ~]# yum install -y ansible
+ 3.查看版本
+ [root@ansiable-server ~]# 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)]
+
+ 4.看帮助
+ [root@ansible-server ~]# ansible --help
+```
+
+## 二:主机清单inventory
+
+ inventory文件通常用于定义要管理主机及其认证信息,例如ssh登录用户名、密码以及key相关信息
+
+#### 1.配置文件
+
+```shell
+vim /etc/ansible/hosts
+ web1 //单独指定主机,可以使用主机名称或IP地址
+ web2
+ web3
+ #-----------------------------------------------------------------
+ [webservers] //使用[]标签指定主机组
+ 192.168.10.128
+ bar.example.com
+ up.example.com:5309 //指定 SSH 端口 5309
+ web5 ansible_ssh_host=web2 //设置主机web2的别名为 web5
+ web1 ansible_ssh_pass='123' //设置ssh密码,使用-k参数之后提示的密码可以不写,直接回车
+ www[01:50].example.com //支持通配符匹配www01,www02,...,www50
+ db-[a:f].example.com //通配符匹配db-a,db-b,...,db-f
+ #-----------------------------------------------------------------
+ 为每个主机单独指定变量,这些变量随后可以在 playbooks 中使用:内置变量
+ [atlanta]
+ host1 http_port=80 maxRequestsPerChild=808
+ host2 http_port=303 maxRequestsPerChild=909
+ #------------------------------------------------------------------
+ 为一个组指定变量,组内每个主机都可以使用该变量:
+ [atlanta]
+ host1
+ host2
+ [atlanta:vars]
+ ansible_ssh_pass='123'
+ ntp_server=ntp.atlanta.example.com
+ proxy=proxy.atlanta.example.com
+ #-----------------------------------------------------------------
+ 组可以包含其他组:
+ [atlanta]
+ host1
+ host2
+ [raleigh]
+ host3
+ host4
+ [southeast:children] //southeast包括两个子组
+ atlanta
+ raleigh
+ [southeast:vars]
+ some_server=foo.southeast.example.com
+ halon_system_timeout=30
+```
+
+ ansible基于ssh连接inventory中指定的远程主机时,还可以通过参数指定其交互方式
+
+```shell
+ ansible_ssh_host # 远程主机
+ ansible_ssh_port # 指定远程主机ssh端口
+ ansible_ssh_user # ssh连接远程主机的用户,默认root
+ ansible_ssh_pass # 连接远程主机使用的密码,在文件中明文,建议使用--ask-pass或者使用SSH keys
+ ansible_sudo_pass # sudo密码, 建议使用--ask-sudo-pass
+ ansible_connection # 指定连接类型: local, ssh, paramiko
+ ansible_ssh_private_key_file # ssh 连接使用的私钥
+ ansible_shell_type # 指定连接对端的shell类型, 默认sh,支持csh,fish
+ ansible_python_interpreter # 指定对端使用的python编译器的路径
+```
+
+#### 2.使用
+
+ 查看组内主机列表
+
+```
+语法:ansible 组名 --list-hosts
+[root@xingdian ~]# ansible web --list-hosts
+ hosts (2):
+ 172.17.0.2
+ 172.17.0.3
+```
+
+ 自定义主机列表
+
+```shell
+vim /home/ansible/hostlist
+[all:vars]
+ansible_ssh_port=22
+ansible_ssh_user=root
+#ansible_ssh_private_key_file=/root/.ssh/id_rsa
+ansible_ssh_pass=1
+[all]
+ansible-web1
+ansible-web2
+```
+
+ 案例
+
+```shell
+[root@ansible-server ~]# ansible -i /opt/hostlist all -m ping -o
+-i:指定清单文件
+```
+
+注意:
+
+```shell
+一个典型的例子就是 shell 和 command 模块. 这两个模块在很多情况下都能完成同样的工作, 以下是两个模块之前的区别:
+command 模块命令将不会使用 shell 执行. 因此, 像 $HOME 这样的变量是不可用的。还有像 |,& 都将不可用
+shell 模块通过shell程序执行, 默认是/bin/sh, <, >, |, ;, & 可用
+```
+
+## 三:点对点Ad-Hoc
+
+ ad hoc 临时的,在ansible中是指需要快速执行,并且不需要保存的命令
+
+ 简单的命令——一条命令;对于复杂的命令则为 playbook
+
+#### 1.ansible模块
+
+ 列出ansible支持的模块:
+
+```shell
+-l:获取列表
+-s module_name:获取指定模块的使用信息
+获取模块列表
+[root@ansible-server ~]# ansible-doc -l
+模块使用格式:
+[root@ansible-server ~]# ansible-doc -s yum
+```
+
+ 模块官方文档:https://docs.ansible.com/ansible/2.9/modules/list_of_files_modules.html
+
+常用模块
+
+**用户管理模块:user**
+
+ 添加用户并设置密码:
+
+```shell
+[root@ansible-server ~]# ansible webservers1 -m user -a "name=liudehua password=`echo 1234 | openssl passwd -1 -stdin`" -o
+"name= " #如:指定的用户名,要安装的软件
+-1 MD5加密算法
+```
+
+ 删除用户:
+
+```shell
+[root@ansible-server ~]# ansible webservers1 -m user -a "name=liudehua state=absent" -o
+adsent #删除用户,但是不会删除家目录
+```
+
+**组管理模块:group**
+
+ 参数:
+
+```shell
+gid:为组设置的可选GID
+name:要管理的组的名称
+state:该组是否应该存在于远程主机上;absent不在/默认是present在
+system:如果是,表示创建的组是系统组;默认时no
+```
+
+ 案例:
+
+```shell
+[root@ansible-server ~]# ansible all -m group -a 'name=somegroup state=present'
+```
+
+**软件包管理模块:yum**
+
+ 参数:
+
+```shell
+config_file:yum的配置文件
+disable_gpg_check:关闭gpg_check
+disablerepo:不启用某个源
+enablerepo:启用某个源
+name:要进行操作的软件包的名字,也可以传递一个url或者一个本地的rpm包的路径
+state:状态(present,absent,latest)
+```
+
+ 安装apache:
+
+```shell
+[root@ansible-server ~]# ansible webservers1 -m yum -a "name=httpd state=latest" -o
+state= #状态是什么,干什么
+state=absent 用于remove安装包
+state=latest 表示最新的
+state=removed 表示卸载
+```
+
+ 卸载软件:
+
+```shell
+[root@ansible-server ~]# ansible webservers1 -m yum -a "name=httpd state=removed" -o
+```
+
+**服务管理模块:service**
+
+ 参数:
+
+```shell
+arguments:给命令行提供一些选项
+enabled:是否开机启动 yes|no
+name:必选项,服务名称
+pattern:定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行
+runlevel:运行级别
+sleep:如果执行了restarted,在则stop和start之间沉睡几秒钟
+state:对当前服务执行启动,停止、重启、重新加载等操作(started,stopped,restarted,reloaded)
+```
+
+ 案例:
+
+```shell
+[root@ansible-server ~]# ansible webservers1 -m service -a "name=httpd state=started" #启动
+[root@ansible-server ~]# ansible webservers1 -m service -a "name=httpd state=stopped" #停止
+[root@ansible-server ~]# ansible webservers1 -m service -a "name=httpd state=restarted" #重启
+[root@ansible-server ~]# ansible webservers1 -m service -a "name=httpd state=started enabled=yes" #开机启动
+[root@ansible-server ~]# ansible webservers1 -m service -a "name=httpd state=started enabled=no" #开机关闭
+```
+
+**文件模块:file**
+
+ 参数:
+
+```shell
+owner:修改属主
+group:修改属组
+mode:修改权限
+path=:要修改文件的路径
+recurse:递归的设置文件的属性,只对目录有效
+ yes:表示使用递归设置
+state:
+touch:创建一个新的空文件
+directory:当目录存在时不会进行修改
+```
+
+ 案例:
+
+```shell
+[root@ansible-server ~]# ansible webservers1 -m file -a 'path=/tmp/88.txt mode=777 state=touch' #创建一个文件
+[root@ansible-server ~]# ansible webservers1 -m file -a 'path=/tmp/99 mode=777 state=directory' #创建一个目录
+```
+
+**收集信息模块:setup**
+
+```shell
+[root@ansible-server ~]# ansible webservers1 -m setup #收集所有信息
+[root@ansible-server ~]# ansible webservers1 -m setup -a 'filter=ansible_all_ipv4_addresses' #只查询ipv4的地址
+filter:过滤
+[root@ansible-server ~]# ansible webservers1 -m setup -a 'filter=ansible_*_mb'
+[root@ansible-server ~]# ansible -i /home/ansible/hostlist web -m setup -a 'filter=ansible_processor_cores'
+[root@ansible-server ~]# ansible all -m setup --tree /tmp/facts
+```
+
+**文件复制模块:copy**
+
+ 参数:
+
+```shell
+backup:在覆盖之前,将源文件备份,备份文件包含时间信息。有两个选项:yes|no
+content:用于替代“src”,可以直接设定指定文件的值
+dest:必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录
+directory_mode:递归设定目录的权限,默认为系统默认权限
+force:如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,默认为yes
+others:所有的file模块里的选项都可以在这里使用
+src:被复制到远程主机的本地文件,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用“/”来结尾,则只复制目录里的内容,如果没有使用“/”来结尾,则包含目录在内的整个内容全部复制
+```
+
+ 案例:
+
+```shell
+[root@ansible-server ~]# ansible test -m copy -a "src=/srv/myfiles/foo.conf dest=/etc/foo.conf owner=foo group=foo mode=0644"
+[root@ansible-server ~]# ansible test -m copy -a "src=/mine/ntp.conf dest=/etc/ntp.conf owner=root group=root mode=644 backup=yes"
+```
+
+**计划任务模块:cron**
+
+ 参数:
+
+```shell
+backup:对远程主机上的原任务计划内容修改之前做备份
+cron_file:如果指定该选项,则用该文件替换远程主机上的cron.d目录下的用户的任务计划
+day:日(1-31,*,*/2,……)
+hour:小时(0-23,*,*/2,……)
+minute:分钟(0-59,*,*/2,……)
+month:月(1-12,*,*/2,……)
+weekday:周(0-7,*,……)
+job:要执行的任务,依赖于state=present
+name:该任务的描述
+special_time:指定什么时候执行,参数:reboot,yearly,annually,monthly,weekly,daily,hourly
+state:确认该任务计划是创建还是删除
+user:以哪个用户的身份执行
+```
+
+ 案例:
+
+```shell
+[root@ansible-server ~]# ansible test -m cron -a 'name="a job for reboot" special_time=reboot job="/some/job.sh"'
+[root@ansible-server ~]# ansible test -m cron -a 'name="yum autoupdate" weekday="2" minute=0 hour=12 user="root
+[root@ansible-server ~]# ansible test -m cron -a 'backup="True" name="test" minute="0" hour="5,2" job="ls -alh > /dev/null"'
+[root@ansible-server ~]# ansilbe test -m cron -a 'cron_file=ansible_yum-autoupdate state=absent'
+```
+
+#### 2.实战案例
+
+ 获取每台主机的IP地址
+
+```shell
+[root@xingdian ~]# ansible -i /home/ansible/hostlist web -m shell -a "ip a | grep eth0| awk 'NR==2{print $2}'" -o > a.txt && cat a.txt |awk '{print $9,$NF}'
+```
+
+ 获取每台主机的内存
+
+```shell
+[root@xingdian ~]# ansible -i /home/ansible/hostlist web -m shell -a "free -m | awk 'NR==2'" > b.txt -o && cat b.txt | awk '{print $10}'
+```
+
+## 四:剧本Playbook
+
+#### 1.介绍
+
+ playbook是ansible用于配置,部署,和管理被控节点的剧本。通过playbook的详细描述,执行其中的tasks,可以让远端主机达到预期的状态。playbook是由一个或多个”play”组成的列表。 当对一台机器做环境初始化的时候往往需要不止做一件事情,这时使用playbook会更加适合。通过playbook你可以一次在多台机器执行多个指令。通过这种预先设计的配置保持了机器的配置统一,并很简单的执行日常任务
+
+#### 2.格式
+
+ playbook由YMAL语言编写。YMAL格式是类似于JSON的文件格式,便于人理解和阅读,同时便于书写
+
+ yaml介绍见另一章
+
+#### 3.核心元素
+
+ Variables #变量元素,可传递给Tasks/Templates使用
+
+ Tasks #任务元素,由模块定义的操作的列表,即调用模块完成任务
+
+ Templates #模板元素,使用了模板语法的文本文件,可根据变量动态生成配置文件
+
+ Handlers #处理器元素,通常指在某事件满足时触发的操作
+
+ Roles #角色元素
+
+注意:
+
+ 一个剧本里面可以有多个play,每个play只能有一个tasks,每个tasks可以有多个name
+
+#### 4.基础组件
+
+name:
+
+ 定义playbook或者task的名称(描述信息),每一个play都可以完成一个任务
+
+hosts:
+
+ playbook中的每一个paly的目的都是为了让某个或某些以某个指定用户的身份执行任务;与命令模式下的ansible匹配规则一样
+
+user:
+
+ remote_user则用于指定远程主机上的执行任务的用户,也可以使用user(基本上是root)
+
+tasks:
+
+ 任务列表play的主体部分是task list. task list中的各任务按次序逐个在hosts中指定的所有主机上执行
+
+vars:
+
+ 定义变量(如果不使用内部变量需要提前定义)
+
+vars_files:
+
+ 调用定义变量文件
+
+notify:
+
+ 任务执行结果如果是发生更改了的则触发定义在handler的任务执行
+
+handlers:
+
+ 用于当前关注的资源发生变化时采取一定指定的操作
+
+include:
+
+ 能包含的包括task,handler和playbook;可以在include的时候传递变量
+
+## 五:剧本案例
+
+#### 1.案例一
+
+```
+[root@ansible-server ~]# cd /etc/ansible/
+[root@ansible-server ansible]# vim test.yml #创建文件必须以.yml结尾
+---
+ - hosts: webservers1
+ user: root
+ tasks:
+ - name: playbook_test
+ file: state=touch path=/tpm/playbook.txt
+```
+
+参数解释
+
+ hosts:参数指定了对哪些主机进行操作
+
+ user:参数指定了使用什么用户登录远程主机操作
+
+ tasks:指定了一个任务
+
+ name:参数同样是对任务的描述,在执行过程中会打印出
+
+检测语法
+
+```shell
+[root@ansible-server ansible]# ansible-playbook --syntax-check test.yml
+playbook: test.yml
+```
+
+运行Playbook
+
+```shell
+[root@ansible-server ansible]# ansible-playbook test.yml
+```
+
+#### 2.案例二
+
+ handlers:由特定条件触发的Tasks
+
+语法
+
+```yaml
+tasks:
+- name: TASK_NAME
+ module: arguments #1.上面任务执行成功,然后
+ notify: HANDLER_NAME #2.通知他
+handlers:
+- name: HANDLER_NAME #3.一一对应,这里的描述与notify定义的必须一样
+ module: arguments #4.执行这个命令
+```
+
+案例
+
+```yaml
+[root@ansible-server ansible]# vim handlers.yml
+- hosts: webservers1
+ user: root
+ tasks:
+ - name: test copy
+ copy: src=/root/a.txt dest=/mnt
+ notify: test handlers
+ handlers:
+ - name: test handlers
+ shell: echo "abcd" >> /mnt/a.txt
+```
+
+注意:
+
+ 只有 copy 模块真正执行后,才会去调用下面的 handlers 相关的操作,追加内容。所以这种比较适合配置文件发生更改后,需要重启服务的操作
+
+检测语法
+
+```shell
+[root@ansible-server ansible]# ansible-playbook --syntax-check handlers.yml
+playbook: handlers.yml
+```
+
+运行剧本
+
+```shell
+[root@ansible-server ansible]# ansible-playbook handlers.yml
+```
+
+#### 3.案例三
+
+安装nginx并启动服务
+
+```
+[root@ansible-server ansible]# vim /home/ansible/yum.yml
+---
+ - hosts: web
+ user: root
+ tasks:
+ - name: install nginx
+ yum: name=nginx state=latest
+ notify: diandian
+ handlers:
+ - name: diandian
+ service: name=nginx state=started
+```
+
+检测语法
+
+```shell
+[root@ansible-server ansible]# ansible-playbook --syntax-check /home/ansible/yum.yml
+playbook: handlers.yml
+```
+
+运行剧本
+
+```shell
+[root@ansible-server ansible]# ansible-playbook /home/ansible/yum.yml
+```
+
+4.案例四
+
+ 循环:迭代,需要重复执行的任务
+
+ 对迭代项的引用,固定变量名为”item”,使用with_items属性给定要迭代的元素
+
+ 元素:1.列表 2.字符串 3.字典
+
+**基于字符串列表元素实战**
+
+```yaml
+[root@ansible-server ansible]# vim list.yml
+- hosts: websrvs
+ remote_user: root
+ tasks:
+ - name: install packages
+ yum: name={{ item }} state=latest #相当于for循环里面的i
+ with_items: #取值 。但是不支持通配符
+ - httpd
+ - php
+ - php-mysql
+ - php-mbstring
+ - php-gd
+```
+
+语法检测
+
+```shell
+[root@ansible-server ansible]# ansible-playbook --syntax-check list.yml
+playbook: list.yml
+```
+
+运行剧本
+
+```shell
+[root@ansible-server ansible]# ansible-playbook list.yml
+```
+
+**基于字典列表给元素示例**
+
+```
+[root@ansible-server ansible]# vim zidian.yml
+- hosts: all
+ user: root
+ tasks:
+ - name: create groups
+ group: name={{ item }} state=present
+ with_items:
+ - groupx1
+ - groupx2
+ - groupx3
+ - name: create users
+ user: name={{ item.name }} group={{ item.group }} state=present
+ with_items: #这里使用的是字典
+ - {name: 'userx1', group: 'groupx1'}
+ - {name: 'userx2', group: 'groupx2'}
+ - {name: 'userx3', group: 'groupx3'}
+```
+
+语法检测
+
+```shell
+[root@ansible-server ansible]# ansible-playbook --syntax-check zidian.yml
+playbook: zidian.yml
+```
+
+运行剧本
+
+```shell
+[root@ansible-server ansible]# ansible-playbook zidian.yml
+```
+
+#### 4.案例四
+
+tags使用
+
+ 给指定的任务定义一个调用标识,形式如下;只运行指定标记的任务:-t tags
+
+```shell
+[root@ansible ansible]# ansible-playbook -t 标记名称 test.yml
+```
+
+ 跳过某一个被标记的任务:--skip-tags=SKIP_TAGS
+
+```shell
+[root@ansible ansible]# ansible-playbook --skip-tags=标记名称 test.yml
+```
+
+ 从某一个任务开始往下运行:--start-at-task 任务名称
+
+```shell
+[root@ansible ansible]# ansible-playbook --start-at-task "start httpd service" test.yml
+```
+
+案例
+
+```yaml
+[root@xingdian /]# vim /home/ansible/tag.yml
+---
+ - hosts: web
+ user: root
+ tasks:
+ - name: touch file
+ file: path=/root/nihao.txt state=touch
+ tags: nihao
+ - name: mkdir file
+ file: path=/root/xingdian state=directory
+ tags: xingdian
+ - name: touch file1
+ file: path=/root/file1.txt state=touch
+ tags: file1
+```
+
+#### 5.案例五
+
+ 批量安装apache服务,并使用浏览器访问到对应的项目
+
+```yaml
+[root@xingdian /]# vim /home/ansible/apache.yml
+---
+ - hosts: web
+ user: root
+ tasks:
+ - name: apache install
+ yum: name=httpd state=latest
+ - name: mkdir file
+ file: path=/web1 state=directory mode=777
+ - name: copy index
+ copy: src=/index.html dest=/web1
+ - name: Listen
+ shell: echo "Listen 81" >> /etc/httpd/conf/httpd.conf
+ - name: copy conf
+ copy: src=/wordpress.conf dest=/etc/httpd/conf.d/
+ notify: start httpd
+ handlers:
+ - name: start httpd
+ service: name=httpd state=restarted
+```
+
+检测语法
+
+```shell
+[root@ansible-server ansible]# ansible-playbook --syntax-check apache.yml
+playbook: list.yml
+```
+
+运行剧本
+
+```shell
+[root@xingdian /]# ansible-playbook /home/ansible/apache.yml
+```
+
+## 六:变量使用
+
+#### 1.语法格式
+
+```shell
+变量调用语法:
+{{ var_name }}
+```
+
+#### 2.案例一
+
+ 通过命令行传递变量:(通过--extra-vars或-e选项来传递key=value变量)
+
+```shell
+[root@xingdian /]# ansible-playbook release.yml -e "user=starbuck"
+```
+
+ 传递字典
+
+```shell
+[root@xingdian ansible]# ansible-playbook conf.yml -e '{"conf81":"/root/81.conf","conf82":"/root/conf82"}'
+```
+
+#### 3.案例二
+
+ 创建变量目录
+
+```shell
+[root@ansible-server ~]# mkdir /etc/ansible/vars
+[root@ansible-server ~]# cd /etc/ansible/vars/
+```
+
+ 创建变量文件
+
+```shell
+[root@ansible-server vars]# vim file.yml
+src_path: /root/test/a.txt
+dest_path: /opt/test/
+```
+
+ 创建一个测试文件
+
+```shell
+[root@ansible-server vars]# mkdir /root/test
+[root@ansible-server vars]# echo 123 >/root/test/a.txt
+```
+
+ 创建playbook引用变量文件
+
+```yaml
+[root@ansible-server vars]# cd /etc/ansible/
+[root@ansible-server ansible]# vim vars.yml
+- hosts: ansible-web1
+ user: root
+ vars_files:
+ - /etc/ansible/vars/file.yml
+ tasks:
+ - name: create directory
+ file: path={{ dest_path }} mode=755 state=directory
+ - name: copy file
+ copy: src={{ src_path }} dest={{ dest_path }}
+```
+
+ 检测语法
+
+```shell
+[root@ansible-server ansible]# ansible-playbook --syntax-check vars.yml
+playbook: vars.yml
+```
+
+ 运行剧本
+
+```shell
+[root@ansible-server ansible]# ansible-playbook vars.yml
+```
+
+#### 4.案例三
+
+ 文件中包含变量
+
+```yaml
+[root@xingdian ansible]# vim conf.yml
+- hosts: web
+ remote_user: root
+ vars:
+ httpd:
+ conf80: /root/80.conf
+ conf8080: /root/8080.conf
+ tasks:
+ - name: task1
+ file:
+ path: "{{httpd.conf80}}"
+ state: touch
+ - name: task2
+ file:
+ path: "{{httpd.conf8080}}"
+ state: touch
+```
+
+ 检测语法
+
+```shell
+[root@xingdian ansible]# ansible-playbook --syntax-check conf.yml
+```
+
+ 运行剧本
+
+```shell
+[root@xingdian ansible]# ansible-playbook conf.yml
+```
+
+#### 5.案例四
+
+ 在主机清单中定义变量
+
+```shell
+[root@xingdian ansible]# tail -5 /etc/ansible/hosts
+[web]
+10.0.0.111
+[web:vars]
+conf81=ppp
+conf82=ooo
+```
+
+ 创建剧本
+
+```yml
+[root@xingdian ansible]# cat conf.yml
+- hosts: web
+ remote_user: root
+ tasks:
+ - name: task1
+ file:
+ path: "{{ conf81 }}"
+ state: touch
+ - name: task2
+ file:
+ path: "{{ conf82 }}"
+ state: touch
+```
+
+ 语法检测
+
+```shell
+[root@xingdian ansible]# ansible-playbook --syntax-check conf.yml
+```
+
+ 运行剧本
+
+```shell
+[root@xingdian ansible]# ansible-playbook conf.yml
+```
+
+#### 6.案例五
+
+ set_fact自定义facts变量
+
+ set_fact模块可以自定义facts,这些自定义的facts可以通过template或者变量的方式在playbook中使用。如果你想要获取一 个进程使用的内存的百分比,则必须通过set_fact来进行计算之后得出其值,并将其值在playbook中引用
+
+ 配置mysql innodb buffer size的示例
+
+```yaml
+ - name: Configure MySQL
+ hosts: web
+ tasks:
+ - name: Calculate InnoDB buffer pool size
+ set_fact: innodb_buffer_pool_size_mb="{{ ansible_swapfree_mb / 2 }}"
+ - name: nihao
+ template: src=/my.cnf dest=/etc/my.cnf owner=root group=root mode=0644
+```
+
+ 参数说明
+
+```shell
+set_fact: innodb_buffer_pool_size_mb="{{ ansible_memtotal_mb / 2 }}"
+ 通过sey_fact去定义,而不是直接执行
+template: src=templates/my.cnf dest=/etc/my.cnf owner=root group=root mode=0644
+ template:这个是一个模板 可以传变量
+```
+
+ my.cnf文件
+
+```shell
+[mysqld]
+datadir=/var/lib/mysql
+socket=/var/lib/mysql/mysql.sock
+# Disabling symbolic-links is recommended to prevent assorted
+security risks
+symbolic-links=0
+
+# Configure the buffer pool
+innodb_buffer_pool_size = {{ innodb_buffer_pool_size_mb|int }}M
+[mysqld_safe]
+log-error=/var/log/mysqld.log
+pid-file=/var/run/mysqld/mysqld.pid
+```
+
+## 七:Role角色
+
+#### 1.介绍
+
+ Roles是在ansible中,playbook的目录组织结构
+
+ 每一个角色是有名字的 ,他是一个目录 ,可以包含子目录
+
+ 以特定的层级目录结构进行组织的tasks、variables、handlers、templates、files等
+
+#### 2.目录作用
+
+role_name:这个是角色的名称
+
+files:存储由copy或script等模块调用的文件
+
+tasks:专门存储任务的目录,一个角色可以定义多个任务;此目录中至少应该有一个名为main.yml的文件,用于定义各task;其它的文件需要由main.yml进行“包含”调用
+
+handlers:条件 前一个任务执行成功去执行下面的,处理特定事物的文件,此目录中至少应该有一个名为main.yml的文件,用于定义各handler;其它的文件需要由main.yml进行“包含”调用
+
+vars:变量 ,定义变量的文件;此目录中至少应该有一个名为main.yml的文件,用于定义各variable;其它的文件需要由main.yml进行“包含”调用
+
+templates:模板 使用变量的文件存储由template模块调用的模板文本
+
+meta:此目录中至少应该有一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要由main.yml进行“包含”调用
+
+default:此目录中至少应该有一个名为main.yml的文件,用于设定默认变量
+
+#### 3.目录案例
+
+ nginx是一个角色的名字,角色里用到文件放在files中,通过创建playbook来调用这些角色
+
+
+
+#### 4.项目案例
+
+ 准备目录结构
+
+```shell
+[root@ansible-server ~]# cd /etc/ansible/roles/ #role位自带目录,如果不存在可以创建
+[root@ansible-server roles]# mkdir nginx/{files,handlers,tasks,templates,vars} -p
+```
+
+ 创建文件
+
+```shell
+[root@ansible-server roles]# touch site.yml nginx/{handlers,tasks,vars}/main.yml
+[root@ansible-server roles]# yum install -y tree
+[root@xingdian roles]# tree nginx/
+nginx/
+├── files
+├── handlers
+│ └── main.yml
+├── tasks
+│ └── main.yml
+├── templates
+└── vars
+ └── main.yml
+
+5 directories, 3 files
+```
+
+ 创建nginx的测试文件
+
+```shell
+[root@ansible-server roles]# echo 1234 > nginx/files/index.html
+```
+
+ 安装nginx并配置模板
+
+```shell
+[root@ansible-server roles]# yum install -y nginx && cp /etc/nginx/nginx.conf nginx/templates/nginx.conf.j2
+```
+
+ 编写任务
+
+```yml
+[root@ansible-server roles]# vim nginx/tasks/main.yml
+---
+- name: install epel
+ yum: name=epel-release state=latest
+- name: install nginx
+ yum: name=nginx state=latest
+- name: copy nginx.conf templte
+ template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
+- name: copy index.html
+ copy: src=index.html dest=/usr/share/nginx/html/index.html
+ notify: start nginx
+```
+
+ templates模板
+
+```shell
+[root@ansible-server roles]# vim nginx/templates/nginx.conf.j2
+```
+
+ 自定义变量
+
+![image-20230303005728244](https://xingdian-image.oss-cn-beijing.aliyuncs.com/xingdian-image/image-20230303005728244.png)
+
+ 编写变量
+
+```shell
+[root@ansible-server roles]# vim nginx/vars/main.yml #添加如下内容
+worker_connections: 2
+```
+
+ 编写handlers
+
+```yaml
+[root@ansible-server roles]# vim nginx/handlers/main.yml #编写如下内容
+---
+- name: start nginx
+ service: name=nginx state=started
+```
+
+ 编写剧本
+
+```yml
+[root@ansible-server roles]# vim site.yml
+---
+- hosts: webservers4
+ user: root
+ roles:
+ - nginx
+```
+
+ 检测语法
+
+```shell
+[root@ansible-server roles]# ansible-playbook site.yml --syntax-check
+playbook: site.yml
+```
+
+ 执行剧本
+
+```shell
+[root@ansible-server roles]# ansible-playbook site.yml
+```
+
+ 查看
+
+```shell
+[root@ansible-web4 ~]# netstat -lntp
+[root@ansible-web4 ~]# cat /etc/nginx/nginx.conf | grep pro
+#worker_processes auto;
+worker_processes 2;
+```
+
+ 访问
+
+```shell
+[root@ansible-web4 ~]# http://172.17.0.2
+```
+
+注意:(了解)
+
+ ansible会使用jinja2模板来修改被管理主机的配置文件;使用ansible的jinja2模板,也就是template模块,该模块和copy模块一样,都是将文件复制到远端主机上;区别在于template模块可以获取要复制的文件中变量的值;而copy则是原封不动的把文件内容复制过去,比如针对不同的主机定义不同的变量,template会在将配置文件分发出去之前读取变量到jinja2模板,然后分发到不通的被管理主机上;ansible允许jinja2模板中使用条件判断和循环,但是jinja2判断循环语法不允许在playbook中使用;jinja2 文件件以 .j2 为后缀, 也可以不写后缀
+
+
+
+
+
diff --git a/ansible/Yaml语法格式.md b/ansible/Yaml语法格式.md
new file mode 100644
index 0000000..2ae0931
--- /dev/null
+++ b/ansible/Yaml语法格式.md
@@ -0,0 +1,172 @@
+Yaml语法格式
+
+------
+
+**作者:行癫(盗版必究)**
+
+## 一:Yaml介绍
+
+ YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写。在开发的这种语言时,YAML 的意思其实是:"Yet Another Markup Language"(仍是一种标记语言);YAML 的语法和其他高级语言类似,并且可以简单表达清单、散列表,标量等数据形态。它使用空白符号缩进和大量依赖外观的特色,特别适合用来表达或编辑数据结构、各种配置文件等;YAML 的配置文件后缀为 .yml,如:runoob.yml*
+
+#### 1.基本语法
+
+ 大小写敏感
+
+ 使用缩进表示层级关系
+
+ 缩进不允许使用tab,只允许空格
+
+ 缩进的空格数不重要,只要相同层级的元素左对齐即可
+
+ '#'表示注释
+
+#### 2.数据类型
+
+ 对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
+
+ 数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
+
+ 纯量(scalars):单个的、不可再分的值
+
+#### 3.Yaml对象
+
+ 对象键值对使用冒号结构表示 key: value,冒号后面要加一个空格
+
+ 也可以使用 key:{key1: value1, key2: value2, ...}
+
+```yaml
+key:
+ child-key: value
+ child-key2: value2
+```
+
+#### 4.Yaml数组
+
+ 以 **-** 开头的行表示构成一个数组
+
+```yaml
+- A
+- B
+- C
+```
+
+ YAML 支持多维数组,可以使用行内表示
+
+```shell
+key: [value1, value2, ...]
+```
+
+ 数据结构的子成员是一个数组,则可以在该项下面缩进一个空格
+
+```shell
+-
+ - A
+ - B
+ - C
+```
+
+ 案例:companies 属性是一个数组,每一个数组元素又是由 id、name、price 三个属性构成
+
+```yaml
+companies:
+ -
+ id: 1
+ name: company1
+ price: 200W
+ -
+ id: 2
+ name: company2
+ price: 500W
+```
+
+#### 5.复合结构
+
+ 数组和对象可以构成复合结构
+
+```yaml
+languages:
+ - Ruby
+ - Perl
+ - Python
+websites:
+ YAML: yaml.org
+ Ruby: ruby-lang.org
+ Python: python.org
+ Perl: use.perl.org
+```
+
+ 转换为 json 为:
+
+```
+{"languages": ["Ruby", "Perl", "Python"], "websites": {"YAML": "yaml.org", "Ruby": "ruby-lang.org", "Python": "python.org", "Perl": "use.perl.org"}}
+
+
+{
+ languages: [ 'Ruby', 'Perl', 'Python'],
+ websites: {
+ YAML: 'yaml.org',
+ Ruby: 'ruby-lang.org',
+ Python: 'python.org',
+ Perl: 'use.perl.org'
+ }
+}
+```
+
+#### 6.纯量
+
+ 纯量是最基本的,不可再分的值,包括:
+
+ 字符串
+
+ 布尔值
+
+ 整数
+
+ 浮点数
+
+ Null
+
+ 时间
+
+ 日期
+
+```yaml
+boolean:
+ - TRUE #true,True都可以
+ - FALSE #false,False都可以
+float:
+ - 3.14
+ - 6.8523015e+5 #可以使用科学计数法
+int:
+ - 123
+ - 0b1010_0111_0100_1010_1110 #二进制表示
+null:
+ nodeName: 'node'
+ parent: ~ #使用~表示null
+string:
+ - 哈哈
+ - 'Hello world' #可以使用双引号或者单引号包裹特殊字符
+ - newline
+ newline2 #字符串可以拆成多行,每一行会被转化成一个空格
+date:
+ - 2018-02-17 #日期必须使用ISO 8601格式,即yyyy-MM-dd
+datetime:
+ - 2018-02-17T15:02:31+08:00 #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
+```
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+