-----ansible-----
查看帮助文档:
ansible-doc -l 列出模块
ansible-doc file #详细
ansible-doc -s file #简略
调试:
检测语法 ansible-playbook --syntax-check rsync.yml
模拟执行 ansible-playbook -C rsync.yml
解决环境变量:
ansible cs1 -m shell -a "source /etc/profile && java -version"
错误:
/usr/lib/python2.7/site-packages/pywin32.pth
/usr/lib64/python2.7/site-packages/pywin32.pth
解决子shell:
ansible 172.17.1.66 -m shell -a "source /etc/profile &>/dev/null;set -m;cd /home/tomcat && find -name startup.sh|xargs -i nohup bash {} &"
set指令能设置所使用shell的执行方式,-m 使用监视模式。
多引号嵌套:
ansible 172.17.1.1 -m cron -a "name='rm_access.log' minute=0 hour=0 job='"'if [ $(ls -l /usr/local/nginx/logs/access.log|awk "{print $5}") -gt 20000000000 ];then cat /usr/local/nginx/logs/access.log >/home/nginx_access.log && >/usr/local/nginx/logs/access.log true;fi'"' "
或者:
ansible 172.17.1.1 -m cron -a 'name="rm_access.log" minute=0 hour=0 job="if [ $(ls -l /usr/local/nginx/logs/access.log|awk \"{print $5}\") -gt 20000000000 ];then cat /usr/local/nginx/logs/access.log >/home/nginx_access.log && >/usr/local/nginx/logs/access.log true;fi"'
切换用户:
ansible oracle -SR oracle -m shell -a 'pwd' #-S sudo -R 制定sudo用户
模块:
setup模块:
格式:
ansible nginx -m setup -a 'filter=ansible_hostname'
ansible nginx -m setup -a 'filter=ansible_*ipv4*' #通配符匹配
常用fact变量:
ansible_all_ipv4_addresses # ipv4的所有地址
ansible_default_ipv4 # 默认的ipv4地址
ansible_hostname #系统的主机名
ansible_env #系统的环境变量
cron模块:
ansible test -m cron -a "name='ntpdate' minute=1 hour=1 day=*/3 job='ntpdate 172.17.1.1' " --每3天的1点1分
ansible test -m cron -a "name='ntpdate' state=absent" --取消任务
file模块:
ansible test -m file -a 'path=/etc/CentOS7.repo state=absent' --删除文件
ansible ansible-demo3 -m file -a "path=/testdir/linkfile1 state=link src=/testdir/testfile1"
copy模块:
ansible all -m copy -a 'src=/usr/bin/history dest=/usr/bin/ mode=777'
fetch
Fetch files from remote nodes(会根据ip保存文件夹,并保持目录结构)
]# ansible node01,node02 -m fetch -a 'src=/etc/hosts dest=/tmp'
template:
]# cat test_template.yml
---
- hosts: node01
#gather_facts: no
vars:
teststr: 'redhat'
testnum: 18
testlist: ['aA','bB','cC']
testlist1:
- AA
- BB
- CC
testdic:
name: pp
age: 22
tpath: "{
{ tpath }}"
tasks:
- template:
src: /root/jinja2/test.j2
dest: /opt/test
]# cat /root/jinja2/test.j2
{
{ teststr }}
{
{ testnum }}
{
{ testlist[1] }}
{
{ testlist1[1] }}
{
{ testdic['name'] }}
ip: {
{ ansible_default_ipv4.address }}
dir: {
{ tpath }}
]# cat /opt/test
redhat
18
bB
BB
pp
ip: 192.168.80.172
dir: /root/test
lineinfile:
常用选项:
regexp: "^DefaultLimitNOFILE.*" #正则匹配
insertafter: xxx #在匹配到的行前插入
insertbefore: xxx #在匹配到的行后插入
line: dest_str #要替换为的目标字符串
backrefs参数:
1 默认情况下,当根据正则替换文本时,即使regexp参数中的正则存在分组,在line参数中也不能对正则中的分组进行引用,除非将backrefs参数的值设置为yes。backrefs=yes表示开启后向引用,这样,line参数中就能对regexp参数中的分组进行后向引用了
2 backrefs=yes除了能够开启后向引用功能,还有另一个作用,默认情况下,当使用正则表达式替换对应行时,如果正则没有匹配到任何的行,那么line对应的内容会被插入到文本的末尾,不过,如果使用了backrefs=yes,情况就不一样了,当使用正则表达式替换对应行时,同时设置了backrefs=yes,那么当正则没有匹配到任何的行时,则不会对文件进行任何操作,相当于保持原文件不变。
3 backrefs=yes,会忽略insertafter和insertbefore参数
backup参数:是否在修改文件之前对文件进行备份。
create参数 :当要操作的文件并不存在时,是否创建对应的文件。
注意:此模块只替换最后一次匹配,多行匹配进行替换需要使用replace模块
例:
- hosts: "{
{host}}"
gather_facts: no
tasks:
- name: modify DefaultLimitNOFILE
lineinfile:
dest: /etc/systemd/system.conf
regexp: "^DefaultLimitNOFILE.*"
line: DefaultLimitNOFILE=100000
- name: modify DefaultLimitNPROC
lineinfile:
dest: /etc/systemd/system.conf
regexp: "^DefaultLimitNPROC.*"
line: DefaultLimitNPROC=65535
- name: daemon-reexec
shell: systemctl daemon-reexec
例2:删除
....
lineinfile:
path: /etc/sudoers
state: absent
regexp: '^%wheel'
replace:
path参数:必须参数,指定要操作的文件
regexp参数:必须参数,指定一个python正则表达式,文件中与正则匹配的字符串将会被替换。
replace参数:指定最终要替换成的字符串。
backup参数:是否在修改文件之前对文件进行备份,最好设置为yes
ansible 172.19.2.74 -m replace -a 'path=/root/system.conf regexp="^#(.*)" replace="\1" backup=yes'
user模块:
user: name=deploy password='$1$kRvBETZa$evc2YK9qSshy2dZvrng4c.' update_password=on_create uid=1025
password 参数用于指定用户密码,但是这个密码不能是明文密码,而是一个对明文密码加密后的字符串,默认为空
openssl passwd -1 '123456'
openssl passwd -1 -salt 'abcdefg' '123456'
update_password 参数可选值有always 和 on_create,默认为always 。 当设置为always时,password参数的值与 /etc/shadow 中密码字符串不一致时更新用户的密码; 当设置为on_create时,password参数的值与 /etc/shadow 中密码字符串不一致时也不会更新用户的密码,但如果是新创建的用户,则此参数即使为on_create,也会更新用户密码。
debug:
- name: uid重复检测
shell: "awk -F: '{print $3}' /etc/passwd|sort|uniq -c|grep -Ev '^\s+1'||echo ok"
register: uid
- debug: var=uid.stdout_lines
expect:
#ansible-doc expect
--history
查看硬盘空间:
ansible all -m shell -a "df -h|grep -v Filesystem|awk -F'[ %]+' '{if(\$5>=80){print \$5\"%\",\$6}}'"
删除上下行都为空的行
^$\r?\n.+\r?\n^$
ansible all -m shell -a "df -h|awk -F'[ T]+' '{if(\$2 ~ /^[0-9]+$/ && \$2>10 || NR==1){print \$0}}'"
启动kibana:
ansible es -m shell -a "su - elastic -c 'nohup kibana-5.6.11-linux-x86_64/bin/kibana &>kibana-5.6.11-linux-x86_64/kibana.log &'"
切换用户执行
ansible testn -m shell -a "su - postgres -c 'pg_ctl status'"
-----Inventory----------
逻辑运算:
与:
ansible zk:\&cs1 -m ping
或:
ansible 192.168.104.1:192.168.104.8 -m ping
或者:ansible 192.168.104.4,192.168.104.8 -m ping
排除主机:
ansible testn:\!172.17.16.81 -m copy -a "src=dbsync dest=/home/postgres/"
playbook中:- hosts: all:!192.168.100.102
通配:
ansible-playbook ntp.yml -e 'host=172.17.17.8*'
正则:
ansible '~(cs1|cs2)_hadoop' -m ping
多主机+通配+排除:
ansible cs1,cs2,cs3:\!hadoop* -m shell -a 'hostname'
分组:
[abc:children] #:children 固定写法
g1
g2
g3
[g1]
172.17.1.6
[g2]
172.17.1.8
[g3]
172.17.1.5
使用:
ansible abc -m ping #所有dbc
ansible abc:\!g1 -m ping #所有dbc(除cho外)
ansible g1:g2 -m ping #调用两个主机组
注意:
分组组名中不能包含'-'
密码:
1, 方式1,直接跟在主机后面
[temp]
172.17.1.8 ansible_ssh_pass='password'
2,方式2,定义分组变量
[temp]
172.17.1.7
172.17.1.8
[temp:vars]
ansible_ssh_pass='password'
其他常用变量:
ansible_ssh_host #用于指定被管理的主机的真实IP
ansible_ssh_port #用于指定连接到被管理主机的ssh端口号,默认是22
ansible_ssh_user #ssh连接时默认使用的用户名
ansible_ssh_pass #ssh连接时的密码
--become
/etc/ansible/hosts
[all:vars]
ansible_ssh_user=test01
ansible_ssh_pass=test123
ansible_ssh_port=22
ansible_become=true
ansible_become_user=root
ansible_become_method='su'
ansible_become_pass=root123
ansible_become_flags='-lc'
----------playbook------------
参数
-v 显示详细信息,也可以用-vv
-i 可以在test.yml中指定hosts,在-i 指定hosts文件中配置,两者取交集
ansible-playbook test.yml -i hosts
常用指令:
gather_facts: no 禁止收集主机信息:
any_errors_fatal: no 强制任何主机上的任何未处理任务错误传播到所有主机并结束播放。
ignore_errors: yes 布尔值,允许您忽略任务失败并继续执行。它不会影响连接错误(可放在tasks中)
remote_user: root 使用的远程用户
vars: 变量,值使用列表
vars_files: 变量文件,值使用列表
变量设置:
方式1:
剧本中编写:
vars:
var_name01: value01
var_name02: value02
方式2:
命令行指定: -e 'var=value'
方式3:
主机清单中
[web:vars]
var_name01=value01
var_name02= value02
优先级:命令行 > 剧本 > 主机清单
变量注册:
- shell: ss -tnlp #常用shell输出注册
register: listen_port #注册变量
- debug: msg={
{ listen_port.stdout_lines }} #显示变量,listen_port是一个字典,stdout_lines是其字段,也可以用listen_port["stdout_lines"]
也可用debug注册:
- debug:
msg:
- "{
{ inventory_hostname }}"
- "{
{ ansible_default_ipv4.gateway }}"
register: res
- debug:
var: res.msg
变量引用:
{
{ var_name }}
debug:(可以输出调试信息msg/var,根据设置输出级别- verbosity)
ansible-doc debug:
- msg
The customized message that is printed. If omitted, prints a generic message.
[Default: Hello world!]
type: str
- var
A variable name to debug.
Mutually exclusive with the `msg' option.
Be aware that this option already runs in Jinja2 context and has an implicit `{
{ }}' wrapping, so you should not be
using Jinja2 delimiters unless you are looking for double interpolation.
[Default: (null)]
type: str
- verbosity #debug的级别(默认是0级,全部显示)
A number that controls when the debug is run, if you set to 3 it will only run debug when -vvv or above
[Default: 0]
type: int
version_added: 2.1
官方示例:
# Example that prints the loopback address and gateway for each host
- debug:
msg: System {
{ inventory_hostname }} has uuid {
{ ansible_product_uuid }}
- debug:
msg: System {
{ inventory_hostname }} has gateway {
{ ansible_default_ipv4.gateway }}
when: ansible_default_ipv4.gateway is defined
# Example that prints return information from the previous task
- shell: /usr/bin/uptime
register: result
- debug:
var: result
verbosity: 2 #-vv 才会显示
- name: Display all variables/facts known for a host
debug:
var: hostvars[inventory_hostname]
verbosity: 4
# Example that prints two lines of messages, but only if there is an environment value set
- debug:
msg:
- "Provisioning based on YOUR_KEY which is: {
{ lookup('env', 'YOUR_KEY') }}"
- "These servers were built using the password of '{
{ password_used }}'. Please retain this for later use."
#打印自定义的信息(调用facts)
- debug: msg="System {
{ inventory_hostname }} has uuid {
{ ansible_product_uuid }}"
# 显示已注册的信息
- debug: msg={
{ register_var.stdout_lines }} #stdout_lines显示列表格式信息,字符串格式可以使用stdout
判断:
基本示例:
- hosts: all
tasks:
- name: "IP if"
debug: msg={
{ansible_default_ipv4.address}}
when: ansible_default_ipv4.address == '192.168.80.172' or not ansible_default_ipv4.address == '192.168.80.173'
#变量不用{
{}}
#等值判断用‘==’,逻辑关键词使用'or','and','not',改变优先级使用小括号()
#多个and可以使用列表'-'
正则匹配:
- hosts: node01
vars:
url: "http://example.com/users/foo/resources/bar"
tasks:
- debug: "msg='matched pattern 1'"
when: url is match("http://example.com/users/.*/resources/.*") #正则判断
- debug: "msg='matched pattern 2'"
when: url is search("/users/.*/resources/.*") #正则判断
- debug: "msg='matched pattern 3'"
when: url is search("/users/") #正则判断 其他类似函数还有,version/subset等,以及文件(directory,file,link,exists)或任务(failed,changed,succeeded,skipped)测试关键字
- debug: msg={
{ url | regex_search("/users/.*/resources/.*") }} #jinja2模板正则过滤器,输出正则匹配的结果,类似还有regex_findall,regex_replace
循环:
循环列表:
- name: install package
yum: name={
{ item }} state=present
with_items:
- wget
- tree
- lrzsz
建议使用另一种格式:
- name: install package
yum:
name: ['wget','tree','lrzsz']
state: present
循环字典:
- name: copy file
copy: src=/etc/ansible/server_file/rsync_server/{
{ item.src }} dest={
{ item.dest }} mode={
{ item.mode }}
with_items:
- { src: 'rsyncd.conf', dest: '/etc/', mode: '644' }
- { src: 'rsync.password', dest: '/etc/', mode: '600' }
标签:
定义:
tasks:
- name: xxx
...
tag: test_tag
使用:
执行标签任务:ansible-playbook --tags=test_tag xxx.yml
跳过标签任务:ansible-playbook --skip-tags=test_tag xxx.yml
触发(handlers):
例:
- hosts: xxx
tasks:
...
- name: push config file
copy: src=... desc=...
notify: restart xxx server
...
handlers:
- name: restart xxx server
service: name=xxx state=restarted
整合: import_playbook
cat main.yml
- import_playbook: base.yml
- import_playbook: xxx.yml
...
roles:
目录结构:
├── site.yml #总配置
├── test
│ ├── files
│ ├── handlers
│ ├── tasks
│ │ └── main.yml
│ ├── templates
│ │ └── main.yml
│ └── vars
│ └── main.yml
└── test02
]# cat site.yml
- hosts: node02
roles:
- test
tags
- hosts: sqlserver
remote_user: root
tasks:
- name: build a new file
copy: content="this is a test" dest=/root/test1.txt
tags:
- only
- name: bulid another file
...
只执行某tag的任务:
ansible-playbook a.yml --tags="only"
给yml传递变量:--extra-var 或 -e
ansible-playbook $PWD/yml/zabbix_agent_install.yml --extra-var "foo=$zabbix_server_ip host=$group"
playbook内引用:
"{
{ foo }}"
"{
{ host }}"
------返回信息、引用facts:
- hosts: "{
{ host }}"
#gather_facts: F #F为禁用收集,默认为True
tasks:
- name: is_pm
shell: "dmidecode |grep -A4 'System Information'|awk -F: '(NR==2){if($2 ~ \".*Xen.*\"){print \"虚拟机\"}else{print \"物理机\"}}'"
register: is_pm_out
- name: show
#debug: var=is_pm_out verbosity=0
debug: var=is_pm_out.stdout verbosity=0 #verbosity 显示信息多少,大于等于3为详细信息
# 多种引用方式:
- debug: var=hostvars[inventory_hostname]['ansible_default_ipv4']['address']
- debug: var=ansible_default_ipv4.address
- debug: msg="ip_addr:{
{ansible_default_ipv4.address}}"
------jianjia模板的循环语句,及使用debug注册变量
dns_var.yml内容(字典+列表):
---
zone_dns:
cs1:
- 172.19.2.13
cs2:
- 172.19.2.12
cs3:
- 172.17.16.69
iv2:
- 172.19.2.68
- 172.19.2.69
---
- hosts: "{
{ host }}"
vars_files:
- dns_var.yml #引用变量文件
tasks:
- name: has 10 net
shell: ifconfig|grep 'inet 10\.'
register: net_10 #shell对象有stdout方法
ignore_errors: yes
# - debug: msg="{
{ net_10.stdout }}"
- name: display
debug: msg="{% for i in zone_dns[zone] %}nameserver {
{ i }}\n{% endfor %}"
register: dns_str #debug也可注册变量
# - debug: msg="{
{ zone_dns[zone][0] }}" #引用列表
- name: set small dns
shell: grep "{
{ zone_dns[zone][0] }}" /etc/resolv.conf || echo -e "{
{ dns_str['msg'] }}" >>/etc/resolv.conf #引用debug注册的变量使用字典
when: net_10.stdout == ''
- name: set big dns
shell: grep '^nameserver 8.8.8.8' /etc/resolv.conf || echo 'nameserver 8.8.8.8' >>/etc/resolv.conf
when: net_10.stdout != ''