ansible使用

一、ansible基本概念#

  • ansible的配置清单位于/etc/ansible/hosts,ansible配置位于/etc/ansible/ansible.cfg
  • ansible依赖与sshpass,配置文件ansible.cfg中需要把host_key_checking=False注释删除
  • 配置清单中,ansible_port为ssh服务端口号,ansible_user为连接到主机使用的用户名,ansible_ssh_pass为用户名对应的密码
  • 配置清单中支持使用主机别名,使用别名后主机IP地址必须使用ansible_host指明
  • ansible也可以基于密钥进行ssh认证
  • ansible保证重复执行的幂等性

二、ansible清单配置详解#

  • 清单支持分组功能,可以将某些主机分为一组,然后通过组明去管理组内的所有主机。ansible [组名] -m ping
  • 清单支持子分组
  • 清单支持INI和YAML两种配置格式
  • 清单中可以定义变量,后续playbook中可以使用

三、ansible模块的基本使用#

  • 使用ansible-doc -l可以查看ansible所有模块的名称和功能呢大概
  • 如需了解具体模块的使用可以使用命令ansible-doc -s [模块名]
  • ansible命令给模块传递参数使用 -a [参数串]
  • ansible命令中的changed说明ansible有没有执行具体操作
  • ansible中的fetch模块是将受管主机中的文件拉渠道ansible主机
  • 对于fetch模块,如果文件的hash值修改了,ansible依旧会执行命令下载新文件,因为ansible会比较文件的hash进行结果判断

四、常用模块之文件操作#

  • copy模块是将ansible主机的文件拷贝到远程主机
  • copy模块常见参数:
    • src 需要copy的文件或目录
    • dest 指定文件被拷贝的远程主机的哪个目录
    • content 文件内容与src二选一
    • force 是否强制覆盖
    • backup 如远程主机目标路径下已存在同名文件,并且与ansible主机文件内容不同时,是否备份
    • owner 指定文件拷贝到远程主机后的属主
    • group 同owner
    • mode 指定文件拷贝到远程主机后的权限
  • file模块可以帮助我们完成一些对文件的基本操作,比如创建文件或目录、删除文件或目录、修改文件权限等
  • file模块常见参数:
    • path 用户指定要操作的文件或目录
    • state 创建文件时用户指定文件类型(directory、touch、link等),删除文件时为absent
    • src state为link或者hard时,表示想要创建一个软链或硬链连接的文件
    • force state为link使用,yes表示强制创建链接
    • owner 指定被操作文件的属主
    • group 指定被操作文件的属组
    • mode 指定被操作文件的权限
    • recurse 操作文件为目录时,recurse=yes可以递归操作目录中的文件
  • blockinfile模块可以帮助我们在指定的文件中插入"一段文本",该文本是被标记过的
  • blockinfile模块常见参数:
    • path 指定要操作的文件
    • block(content) 文本
    • marker 指定标记
    • state present表示插入或更新,absent表示删除标记文本
    • insertafter 使用此参数指定对应的行后面插入,也可以使用正则表达式指定插入位置
    • insertbefore 同上
    • backup 修改文件之前对文件进行备份
    • create 当要操作的文件不存在,是否创建文件
  • lineinfile模块可以确保某一行文本存在与指定文件中,或者确保删除指定文本,还可以根据正则替换某一行文本
  • lineinfile模块常见参数:
    • path 表示要操作的文件
    • line 文本内容
    • regexp 使用正则表达式匹配对应的行,多行匹配时只有最后面那行会被替换,如果是删除则全部匹配都会删除
    • state absent和present
    • backrefs 表示开启正则表达式后向引用
    • insertafter 使用此参数指定对应的行后面插入,也可以使用正则表达式指定插入位置
    • insertbefore 同上
    • backup 修改文件之前对文件进行备份
    • create 当要操作的文件不存在,是否创建文件

五、常用模块之文件操作(二)#

  • find模块可以帮助我们在远程主机中查找符合条件的文件
  • find模块常见参数:
    • paths 搜索路径,可以使用name或path替代
    • rescurse recurse=yes可以递归查找文件
    • hidden 默认情况下,隐藏文件会被忽略,hidden=yes则会查找隐藏文件
    • file_type 默认情况下指挥查找"文件",file_type可以指定文件类型,all、directory、file、link
    • patterns 文件名,支持shell或正则表达式去匹配文件名称
    • user_regex yes表示支持patterns使用正则
    • contains 匹配文件内容,使用正则
    • age 默认以文件mtime为准与指定时间进行对比
    • age_stamp age的时间属性atime、ctime、mtime
    • size 根据文件大小查找文件
    • get_checksum 返回对应文件的sha1校验码
  • replace模块可以根据我们指定的正则表达式替换文件中的字符串
  • replace模块常见参数:
    • path 要操作的文件
    • regexp 正则表达式
    • replace 最终要替换成的字符串
    • backup 是否在修改前备份文件

六、常用模块之命令类模块#

  • command模块可以帮助我们在远程主机上执行命令
  • command模块常见参数:
    • free_form 需要执行的命令
    • chdir 执行命令前会先进入到chdir参数指定的目录中
    • creates 当指定文件存在就不执行对应命令
    • removes 当指定文件不存在就不指定对应命令
  • shell模块与command模块不同的是,shell模块执行命令时,会经过远程主机上的/bin/sh程序处理
  • shell模块常见参数包含command模块四个参数:
    • executable 指定其他类型的shell执行命令,默认shell都是bash
  • script模块可以帮助我们在远程主机上执行ansible主机上的脚本,脚本存在与ansible主机不需要拷贝到远程主机再执行
  • script常见参数与command模块相同,free_form表示要执行的脚本

七、 常用模块之系统类模块#

  • cron模块可以帮助我们管理远程主机上的计划任务,相当于crontab
  • cron模块常见参数:
    • minute 设置计划任务中分钟设定为的值
    • hour 设置计划任务中小时设定为的值
    • day 设置计划任务中日设定为的值
    • month 设置计划任务中月设定为的值
    • weekday 设置计划任务中周几设定为的值
    • special_time 比如@reboot表示重启时@hourly表示每小时执行一次
    • user 计划任务属于哪个用户
    • job 任务实际执行的命令或脚本
    • name 计划任务名称
    • state 删除任务为absent
    • disabled 根据名称使对应任务失效
    • backup yes会对计划任务进行备份
  • service模块可以帮助我们管理远程主机上的服务
  • service模块常见参数:
    • name 服务名称
    • state 此参数值有started、stopped、restarted、reloaded
    • enabled 将服务设置为开机启动项

八、 常用模块之系统类模块(二)#

  • user模块可以帮助我们管理远程主机上的用户
  • user模块常见参数:
    • name 用户名称,别名user
    • group 指定用户所在的基本组
    • groups 指定用户所在的夫家族
    • append yes表示追加附加组
    • shell 指定用户的默认shell
    • uid 指定用户的uid
    • expires 指定用户的过期时间
    • comment 指定用户的注释信息
    • state present和absent
    • remove yes表示删除用户时会删除用户的home目录
    • password 指定用户的密码
    • generate_ssh_key yes表示为对应的用户生成ssh密钥对
    • ssh_key_file yes表示自定义生成ssh私钥的路径和名称
  • group模块可以帮助我们管理远程主机上的组
  • group模块常见参数:
    • name 组名称
    • state present和absent
    • gid 组的gid

九、常用模块值包管理模块#

  • yum_repository模块可以帮助我们管理远程主机上的yum仓库
  • yum模块可以帮助我们在远程主机上通过yum源管理软件包

十、初识ansible playbook#

  • 多条ansible命令可以用ansible playbook完成
  • ansible playbook配置文件是YAML格式的
  • ansible-playbook用于运行playbook文件
  • 一个playbook文件中可以编写多个play
  • ansible-playbook --syntax-check [yaml文件]可以检查playbook文件是否存在语法错误
  • ansible-playbook --check [yaml文件]可以模拟执行playbook

十一、初识ansible playbook(二)#

  • ansible playbook的不同写法
  • 推荐下面的写法
Copy
--- - hosts: test70 remote_user: root tasks: - name: make testfile file: path: /testdir/testfile state: touch mode: 0700

tasks中也可以这么写

Copy
tasks: - name: make testfile file: path=/testdir/testfile state=touch mode=0700

file后面的参数可以换行,但是要注意缩进

Copy
tasks: - name: make testfile file: path=/testdir/testfile state=touch mode=0700

比较老的版本会使用action关键字调用模块

Copy
tasks: - name: make testfile action: file path=/testdir/testfile state=touch mode=0700

十二、handlers的用法#

  • handlers可以解决当tasks任务真正执行以后,handlers中被调用的任务才会执行
    example,当配置文件真正被修改后才重启nginx服务,否则不重启:
Copy
--- - hosts: test70 remote_user: root tasks: - name: Modify the configuration lineinfile: path=/etc/nginx/conf.d/test.zsythink.net.conf regexp="listen(.*) 8080(.*)" line="listen\1 8088\2" backrefs=yes backup=yes notify: restart nginx handlers: - name: restart nginx service: name=nginx state=restarted
  • 默认情况下,只有全部tasks都执行完毕才会执行handler。handlers的执行顺序和在playbook中定义的顺序是相同的,与被notify的顺序无关
  • meta模块是一种特殊任务,可以影响aansible的内部运行方式,参数值为flush_handlers表示立即执行之前的task所对应的handlers
  • 一次性notify多个handler可以使用listen关键字
Copy
--- - hosts: test70 remote_user: root tasks: - name: task1 file: path=/testdir/testfile state=touch notify: handler group1 handlers: - name: handler1 listen: handler group1 file: path=/testdir/ht1 state=touch - name: handler2 listen: handler group1 file: path=/testdir/ht2 state=touch

十三、tags的用法#

  • tags可以帮助我们对任务进行打标签,当任务存在标签后,我们就可以在执行playbook的时候传入标签指定执行哪些任务
Copy
--- - hosts: test70 remote_user: root tags: file tasks: - name: task1 file: path: /testdir/t1 state: touch tags: t1 - name: task2 file: path=/testdir/t2 state=touch tags: - t2 - name: task3 file: path=/testdir/t3 state=touch tags: ['t3']
Copy
ansible-playbook --tags=t2 testtag.yml ansible-playbook --skip-tags=t2 testtag.yml
  • tags还可以写在play上,play下的所有tasks继承play的tags
  • ansible预置了5个特殊tag,分别是always、never、tagged、untagged、all
  • always、never用于yaml配置文件中,tagged、untagged、all用于执行ansible-playbook命令

十四、变量(一)#

  • 在play文件中定义变量,可以借助vars关键字,使用变量可以用{{变量名}}
Copy
--- - hosts: test70 vars: testvar1: testfile testvar2: testfile2 remote_user: root tasks: - name: task1 file: path: /testdir/{{ testvar1 }} state: touch
  • 变量可以多层级定义
Copy
--- - hosts: test70 remote_user: root vars: nginx: conf80: /etc/nginx/conf.d/80.conf conf8080: /etc/nginx/conf.d/8080.conf tasks: - name: task1 file: path: "{{nginx.conf80}}" state: touch - name: task2 file: path: "{{nginx.conf8080}}" state: touch
  • 引用变量时,如果处在开头未知,需要用双引号引起变量
  • playbook中的变量可以与配置文件分离,在配置文件中使用vars_files关键字进行引入
Copy
--- - hosts: test70 remote_user: root vars_files: - /testdir/ansible/nginx_vars.yml tasks: - name: task1 file: path={{nginx.conf80}} state=touch - name: task2 file: path={{nginx['conf8080']}} state=touch

十五、变量(二)#

  • 当我们运行一个playbook时,默认都会运行一个名为Gathering Facts的任务,这个默认任务收集远程主机的相关信息并保存到对应的变量中,我们可以通过ansible [hosts] -m setup查看这些变量,也可以在playbook配置文件中使用这些变量
    • ansible_all_ipv4_addresses 表示主机上的所有ipv4的地址
    • ansible_distribution 表示主机的系统发行版本
    • ansible_distribution_version 表示主机的系统版本号
    • ansible_memory_mb 表示内存配置信息
  • 我们还可以在受管主机中写入一些自定义的信息,这些自定义信息可以写在/etc/ansible/facts.d目录下,自定义信息文件必须以.fact结尾,文件内容时INI格式或者json格式
  • 自定义信息的目录可以通过setup模块的fact_path参数进行定义
  • debug模块是用来帮助我们调试的,可以将信息输出到ansible控制台

十六、变量(三)#

  • 使用register可以将模块的返回值写入到变量中,称作注册变量
  • 模块的返回值为json格式,可以使用.或者[]获取json中特定项的值
  • 使用vars_prompt关键字提示用户输入信息并写入变量
Copy
--- - hosts: test70 remote_user: root vars_prompt: - name: "your_name" prompt: "What is your name" - name: "your_age" prompt: "How old are you" tasks: - name: output vars debug: msg: Your name is {{your_name}},You are {{your_age}} years old.
  • 通过命令行也可以传入变量,命令行变量的优先级要高于playbook中的变量
Copy
ansible-playbook cmdvar.yml -e 'pass_var="test" pass_var1="test1"'

十七、变量(四)#

  • 在清单中配置主机信息时,可以同时为主机配置对应的变量
  • 为主机组配置变量可以这样做
Copy
[testB] test70 ansible_host=10.1.1.70 test71 anisble_host=10.1.1.71 [testB:vars] test_group_var1='group var test' test_group_var2='group var test2'
  • set_fact模块可以让我们在tasks中定义变量
  • 通过set_fact创建的变量就像主机上的额facts信息,可以在之后的play中被引用(注册变量也可以在之后的play中引用)
    以下示例中,testvar1不能被正常输出,testvar2却可以
Copy
--- - hosts: test70 remote_user: root vars: testvar1: tv1 tasks: - set_fact: testvar2: tv2 - debug: msg: "{{testvar1}} ----- {{testvar2}}" - hosts: test70 remote_user: root tasks: - name: other play get testvar2 debug: msg: "{{testvar2}}" - name: other play get testvar1 debug: msg: "{{testvar1}}"

十八、变量(五)#

  • 内置变量ansible_version可以获取到ansible版本号
Copy
ansible test70 -m debug -a "msg={{ansible_version}}"
  • 内置变量hostvars可以帮助我们在操作当前主机的时候获取其他主机中的信息,包括注册变量、主机变量、组变量等信息
  • 内置变量inventory_hostname可以获取当前主机的主机名,对应主机在清单中配置的名称
  • 内置变量inventory_hostname_short可以获取当前主机的主机名第一个"."之前的字符作为主机的简称
  • 内置变量play_hosts可以获取到当前play所操作的所有主机的主机名列表
  • 内置变量groups可以获取到清单中所有分则的分则信息
  • 内置变量group_names可以获取当前主机所在分组的组名
  • 内置变量inventory_dir可以获取ansible主机中清单文件的存放路径

十九、循环(一)#

  • 关键字with_items可以接收列表信息并使用{{item}}迭代列表的每一项
Copy
--- - hosts: test70 remote_user: root gather_facts: no tasks: - debug: msg: "{{item}}" with_items: "{{groups.ungrouped}}"

使用循环可以简化playbook文件配置,比如在主机上创建四个文件

Copy
--- - hosts: test70 remote_user: root gather_facts: no tasks: - file: path: "/opt/a" state: touch - file: path: "/opt/b" state: touch - file: path: "/opt/c" state: touch - file: path: "/opt/d" state: touch

可以使用循环简化为

Copy
--- - hosts: test70 remote_user: root gather_facts: no vars: dirs: - "/opt/a" - "/opt/b" - "/opt/c" - "/opt/d" tasks: - file: path: "{{item}}" state: touch with_items: "{{dirs}}"
  • 使用循环后注入变量,会让变量列表放在results属性中
Copy
--- - hosts: test70 gather_facts: no tasks: - shell: "{{item}}" with_items: - "ls /opt" - "ls /home" register: returnvalue - debug: msg: "{% for i in returnvalue.results %} {{ i.stdout }} {% endfor %}"

二十、循环(二)#

  • with_item如果是嵌套列表,循环会处理每个小列表中的值
  • with_list处理嵌套列表,只会处理到第一层列表的元素
  • 处理单层列表时,with_items和with_list有一样的效果
  • with_flattened与with_items效果一样
  • with_together可以将两个列表中的元素对其合并
Copy
--- - hosts: test70 remote_user: root gather_facts: no tasks: - debug: msg: "{{ item }}" with_together: - [ 1, 2, 3 ] - [ a, b, c ]

输出结果:

Copy
TASK [debug] ****************************** ok: [test70] => (item=[1, u'a']) => { "changed": false, "item": [ 1, "a" ], "msg": [ 1, "a" ] } ok: [test70] => (item=[2, u'b']) => { "changed": false, "item": [ 2, "b" ], "msg": [ 2, "b" ] } ok: [test70] => (item=[3, u'c']) => { "changed": false, "item": [ 3, "c" ], "msg": [ 3, "c" ] }
  • 如果with_together中两个列表长度不一致,缺失的部分会用null替代

二十一、循环(三)#

  • with_cartesian可以进行嵌套循环,可以用with_nested,效果一致
    创建三个文件夹,并且都包含test1和test2两个文件
Copy
--- - hosts: test70 remote_user: root gather_facts: no tasks: - debug: msg: "{{ item }}" with_cartesian: - [ a, b, c ] - [ test1, test2 ]

二十二、循环(四)#

  • with_indexed_items可以给循环列表加上数字索引,获取数字索引{{item.0}}
  • with_indexed_items可以将"两层"嵌套列表"拉平",然后按照顺序为每一项编号。不支持多层嵌套

二十三、循环(五)#

  • with_sequence可以执行循环开始和结束,以及步长
    比如要创建test2、test4、test6、test8、test10五个文件,示例如下:
Copy
--- - hosts: test70 remote_user: root gather_facts: no tasks: - debug: msg: "{{ item }}" with_sequence: start=2 end=10 stride=2
  • with_sequence还可以格式化输出数据
Copy
--- - hosts: test70 remote_user: root gather_facts: no tasks: - debug: msg: "{{item}}" with_sequence: start=2 end=6 stride=2 format="number is %0.2f"
  • with_random_choice可以从列表中多个值随机返回一个值

二十四、循环(六)#

  • with_dict可以循环"字典",将键值对中的键放入key关键字,值放入value关键字中
Copy
--- - hosts: test70 remote_user: root gather_facts: no vars: users: alice: female bob: male tasks: - debug: msg: "{{item}}" with_dict: "{{users}}"
  • with_subelements可以在处理列表时,指定一个属性
Copy
--- - hosts: test70 remote_user: root gather_facts: no vars: users: - name: bob gender: male hobby: - Skateboard - VideoGame - name: alice gender: female hobby: - Music tasks: - debug: msg: "{{ item.0.name }} 's hobby is {{ item.1 }}" with_subelements: - "{{users}}" - hobby

循环过程中的item为

Copy
(item=({u'gender': u'male', u'name': u'bob'}, u'Skateboard')) => { "changed": false, "item": [ { "gender": "male", "name": "bob" }, "Skateboard" ] }

结果为

Copy
"msg": "bob 's hobby is Skateboard" "msg": "bob 's hobby is VideoGame" "msg": "alice 's hobby is Music"

二十五、循环(七)#

  • with_file可以获取ansible主机的文件
  • with_fileglob用来匹配文件名称,在指定目录中匹配符合模式的文件名,也是针对ansible主机文件,不是远程主机
  • with_fileglob只能匹配文件,不包含目录

二十六、条件判断#

  • when作为条件判断的关键字
    比如判断条件是Centos系统才执行task
Copy
--- - hosts: test70 remote_user: root tasks: - debug: msg: "System release is centos" when: ansible_distribution == "CentOS"
  • 在循环中使用条件判断
Copy
--- - hosts: test70 remote_user: root gather_facts: no tasks: - debug: msg: "{{ item }}" with_items: - 1 - 2 - 3 when: item > 1
  • 条件判断中的逻辑操作符为and和or,取非为not [condition]

二十七、条件判断与tests#

  • tests可以进行一些判断操作
Copy
--- - hosts: test70 remote_user: root gather_facts: no vars: testpath: /testdir tasks: - debug: msg: "file exist" when: testpath is exists

is exists中exists是tests的一种,与test -e命令作用相同

  • 判断变量的一些tests
    • defined :判断变量是否已经定义,已经定义则返回真
    • undefind :判断变量是否已经定义,未定义则返回真
    • none :判断变量值是否为空,如果变量已经定义,但是变量值为空,则返回真
  • 判断执行结果的一些tests
    • success 或 succeeded:通过任务的返回信息判断任务的执行状态,任务执行成功则返回真
    • failure 或 failed:通过任务的返回信息判断任务的执行状态,任务执行失败则返回真
    • change 或 changed:通过任务的返回信息判断任务的执行状态,任务执行状态为changed则返回真
    • skip 或 skipped:通过任务的返回信息判断任务的执行状态,当任务没有满足条件,而被跳过执行时,则返回真
  • 判断路径的一些tests
    • file : 判断路径是否是一个文件,如果路径是一个文件则返回真
    • directory :判断路径是否是一个目录,如果路径是一个目录则返回真
    • link :判断路径是否是一个软链接,如果路径是一个软链接则返回真
    • mount:判断路径是否是一个挂载点,如果路径是一个挂载点则返回真
    • exists:判断路径是否存在,如果路径存在则返回真
  • 判断字符串的一些tests
    • lower:判断包含字母的字符串中的字母是否是纯小写,字符串中的字母全部为小写则返回真
    • upper:判断包含字母的字符串中的字母是否是纯大写,字符串中的字母全部为大写则返回真
  • 判断整除的一些tests
    • even :判断数值是否是偶数,是偶数则返回真
    • odd :判断数值是否是奇数,是奇数则返回真
    • divisibleby(num) :判断是否可以整除指定的数值,如果除以指定的值以后余数为0,则返回真
  • 其他常用的tests判断
    • subset:判断一个list是不是另一个list的子集,是另一个list的子集时返回真
    • superset : 判断一个list是不是另一个list的父集,是另一个list的父集时返回真
    • string:判断对象是否是一个字符串,是字符串则返回真
    • number:判断对象是否是一个数字,是数字则返回真

二十八、条件判断与block#

  • 使用when可以对条件进行判断,当条件成立执行对应的任务。如果需要条件成立执行多个任务,需要使用block关键字
  • block可以将多个任务整合成一个块,并把这个块当作一个整体
  • 关键字rescue可以在block任务执行失败时执行进行不久,如果block中的任务顺利执行就不会执行rescue中的任务
  • 关键字always无论block执行成功还是失败,always中的任务都会被执行

二十九、条件判断与错误处理#

  • 在执行playbook时,如果任何一个任务执行失败,playbook都会停止运行,除非这个任务设置了ignore_errors: true
  • fail模块就是一个用来"执行失败"的模块,当fail模块执行后,playbook就会认为有任务失败而终止运行
  • fail模块加上条件判断when可以达到根据执行过程中一些结果输出而终止运行
  • 关键字failed_when也可以达到此效果,条件成立将对应任务的执行状态设置为失败
  • 关键字changed_when的作用时条件成立,将对应任务的执行状态设置为changed

三十、过滤器(一)#

  • 过滤器可以帮助我们对数据进行处理
  • ansible的过滤器功能来自于jinja2模板引擎
    字符串相关的过滤器
Copy
--- - hosts: test70 remote_user: root vars: testvar: "abc123ABC 666" testvar1: " abc " testvar2: '123456789' testvar3: "1a2b,@#$%^&" tasks: - debug: #将字符串转换成纯大写 msg: "{{ testvar | upper }}" - debug: #将字符串转换成纯小写 msg: "{{ testvar | lower }}" - debug: #将字符串变成首字母大写,之后所有字母纯小写 msg: "{{ testvar | capitalize }}" - debug: #将字符串反转 msg: "{{ testvar | reverse }}" - debug: #返回字符串的第一个字符 msg: "{{ testvar | first }}" - debug: #返回字符串的最后一个字符 msg: "{{ testvar | last }}" - debug: #将字符串开头和结尾的空格去除 msg: "{{ testvar1 | trim }}" - debug: #将字符串放在中间,并且设置字符串的长度为30,字符串两边用空格补齐30位长 msg: "{{ testvar1 | center(width=30) }}" - debug: #返回字符串长度,length与count等效,可以写为count msg: "{{ testvar2 | length }}" - debug: #将字符串转换成列表,每个字符作为一个元素 msg: "{{ testvar3 | list }}" - debug: #将字符串转换成列表,每个字符作为一个元素,并且随机打乱顺序 #shuffle的字面意思为洗牌 msg: "{{ testvar3 | shuffle }}" - debug: #将字符串转换成列表,每个字符作为一个元素,并且随机打乱顺序 #在随机打乱顺序时,将ansible_date_time.epoch的值设置为随机种子 #也可以使用其他值作为随机种子,ansible_date_time.epoch是facts信息 msg: "{{ testvar3 | shuffle(seed=(ansible_date_time.epoch)) }}"

与数字相关的过滤器

Copy
--- - hosts: test70 remote_user: root vars: testvar4: -1 tasks: - debug: #将对应的值转换成int类型 #ansible中,字符串和整形不能直接计算,比如{{ 8+'8' }}会报错 #所以,我们可以把一个值为数字的字符串转换成整形后再做计算 msg: "{{ 8+('8' | int) }}" - debug: #将对应的值转换成int类型,如果无法转换,默认返回0 #使用int(default=6)或者int(6)时,如果无法转换则返回指定值6 msg: "{{ 'a' | int(default=6) }}" - debug: #将对应的值转换成浮点型,如果无法转换,默认返回'0.0' msg: "{{ '8' | float }}" - debug: #当对应的值无法被转换成浮点型时,则返回指定值’8.8‘ msg: "{{ 'a' | float(8.88) }}" - debug: #获取对应数值的绝对值 msg: "{{ testvar4 | abs }}" - debug: #四舍五入 msg: "{{ 12.5 | round }}" - debug: #取小数点后五位 msg: "{{ 3.1415926 | round(5) }}" - debug: #从0到100中随机返回一个随机数 msg: "{{ 100 | random }}" - debug: #从5到10中随机返回一个随机数 msg: "{{ 10 | random(start=5) }}" - debug: #从5到15中随机返回一个随机数,步长为3 #步长为3的意思是返回的随机数只有可能是5、8、11、14中的一个 msg: "{{ 15 | random(start=5,step=3) }}" - debug: #从0到15中随机返回一个随机数,这个随机数是5的倍数 msg: "{{ 15 | random(step=5) }}" - debug: #从0到15中随机返回一个随机数,并将ansible_date_time.epoch的值设置为随机种子 #也可以使用其他值作为随机种子,ansible_date_time.epoch是facts信息 #seed参数从ansible2.3版本开始可用 msg: "{{ 15 | random(seed=(ansible_date_time.epoch)) }}"

与列表相关的过滤器

Copy
--- - hosts: test70 remote_user: root vars: testvar7: [22,18,5,33,27,30] testvar8: [1,[7,2,[15,9]],3,5] testvar9: [1,'b',5] testvar10: [1,'A','b',['QQ','wechat'],'CdEf'] testvar11: ['abc',1,3,'a',3,'1','abc'] testvar12: ['abc',2,'a','b','a'] tasks: - debug: #返回列表长度,length与count等效,可以写为count msg: "{{ testvar7 | length }}" - debug: #返回列表中的第一个值 msg: "{{ testvar7 | first }}" - debug: #返回列表中的最后一个值 msg: "{{ testvar7 | last }}" - debug: #返回列表中最小的值 msg: "{{ testvar7 | min }}" - debug: #返回列表中最大的值 msg: "{{ testvar7 | max }}" - debug: #将列表升序排序输出 msg: "{{ testvar7 | sort }}" - debug: #将列表降序排序输出 msg: "{{ testvar7 | sort(reverse=true) }}" - debug: #返回纯数字非嵌套列表中所有数字的和 msg: "{{ testvar7 | sum }}" - debug: #如果列表中包含列表,那么使用flatten可以'拉平'嵌套的列表 #2.5版本中可用,执行如下示例后查看效果 msg: "{{ testvar8 | flatten }}" - debug: #如果列表中嵌套了列表,那么将第1层的嵌套列表‘拉平’ #2.5版本中可用,执行如下示例后查看效果 msg: "{{ testvar8 | flatten(levels=1) }}" - debug: #过滤器都是可以自由结合使用的,就好像linux命令中的管道符一样 #如下,取出嵌套列表中的最大值 msg: "{{ testvar8 | flatten | max }}" - debug: #将列表中的元素合并成一个字符串 msg: "{{ testvar9 | join }}" - debug: #将列表中的元素合并成一个字符串,每个元素之间用指定的字符隔开 msg: "{{ testvar9 | join(' , ') }}" - debug: #从列表中随机返回一个元素 #对列表使用random过滤器时,不能使用start和step参数 msg: "{{ testvar9 | random }}" - debug: #从列表中随机返回一个元素,并将ansible_date_time.epoch的值设置为随机种子 #seed参数从ansible2.3版本开始可用 msg: "{{ testvar9 | random(seed=(ansible_date_time.epoch)) }}" - debug: #随机打乱顺序列表中元素的顺序 #shuffle的字面意思为洗牌 msg: "{{ testvar9 | shuffle }}" - debug: #随机打乱顺序列表中元素的顺序 #在随机打乱顺序时,将ansible_date_time.epoch的值设置为随机种子 #seed参数从ansible2.3版本开始可用 msg: "{{ testvar9 | shuffle(seed=(ansible_date_time.epoch)) }}" - debug: #将列表中的每个元素变成纯大写 msg: "{{ testvar10 | upper }}" - debug: #将列表中的每个元素变成纯小写 msg: "{{ testvar10 | lower }}" - debug: #去掉列表中重复的元素,重复的元素只留下一个 msg: "{{ testvar11 | unique }}" - debug: #将两个列表合并,重复的元素只留下一个 #也就是求两个列表的并集 msg: "{{ testvar11 | union(testvar12) }}" - debug: #取出两个列表的交集,重复的元素只留下一个 msg: "{{ testvar11 | intersect(testvar12) }}" - debug: #取出存在于testvar11列表中,但是不存在于testvar12列表中的元素 #去重后重复的元素只留下一个 #换句话说就是:两个列表的交集在列表1中的补集 msg: "{{ testvar11 | difference(testvar12) }}" - debug: #取出两个列表中各自独有的元素,重复的元素只留下一个 #即去除两个列表的交集,剩余的元素 msg: "{{ testvar11 | symmetric_difference(testvar12) }}"

与变量未定义相关的过滤器

Copy
--- - hosts: test70 remote_user: root gather_facts: no vars: testvar6: '' tasks: - debug: #如果变量没有定义,则临时返回一个指定的默认值 #注:如果定义了变量,变量值为空字符串,则会输出空字符 #default过滤器的别名是d msg: "{{ testvar5 | default('zsythink') }}" - debug: #如果变量的值是一个空字符串或者变量没有定义,则临时返回一个指定的默认值 msg: "{{ testvar6 | default('zsythink',boolean=true) }}" - debug: #如果对应的变量未定义,则报出“Mandatory variable not defined.”错误,而不是报出默认错误 msg: "{{ testvar5 | mandatory }}"

三十一、变量(六)#

  • vars_files只能在一开始就引入文件中的所有变量,如果需要动态获取到最新的变量文件内容需要使用include_vars
Copy
--- - hosts: test71 remote_user: root gather_facts: no vars_files: - /testdir/ansible/testfile tasks: - debug: msg: "{{testvar3}}" - lineinfile: path: "/testdir/ansible/testfile" line: "testvar4: ddd" - include_vars: "/testdir/ansible/testfile" - debug: msg: "{{testvar4}}"
  • include_vars可以将文件中的全部变量赋值给另一个变量
  • include_vars可以将指定目录的所有变量文件加载进来
  • include_vars还有其他属性,extensions、depth、files_matching、ignore_files

三十二、过滤器(二)#

  • json_query过滤器可以获取json中指定属性的值

三十三、过滤器(三)#

  • 常用的过滤器
Copy
--- - hosts: test70 remote_user: root gather_facts: no tasks: ###################################################################### #在调用shell模块时,如果引用某些变量时需要添加引号,则可以使用quote过滤器代替引号 #示例如下,先看示例,后面会有注解 - shell: "echo {{teststr | quote}} > /testdir/testfile" vars: teststr: "a\nb\nc" #上例中shell模块的写法与如下写法完全等效 #shell: "echo '{{teststr}}' > /testdir/testfile" #没错,如你所见,quote过滤器能够代替引号 #上例中,如果不对{{teststr}}添加引号,则会报错,因为teststr变量中包含"\n"转义符 ###################################################################### #ternary过滤器可以实现三元运算的效果 示例如下 #如下示例表示如果name变量的值是John,那么对应的值则为Mr,否则则为Ms #简便的实现类似if else对变量赋值的效果 - debug: msg: "{{ (name == 'John') | ternary('Mr','Ms') }}" vars: name: "John" ###################################################################### #basename过滤器可以获取到一个路径字符串中的文件名 - debug: msg: "{{teststr | basename}}" vars: teststr: "/testdir/ansible/testfile" ###################################################################### #获取到一个windows路径字符串中的文件名,2.0版本以后的ansible可用 - debug: msg: "{{teststr | win_basename}}" vars: teststr: 'D:\study\zsythink' ###################################################################### #dirname过滤器可以获取到一个路径字符串中的路径名 - debug: msg: "{{teststr | dirname}}" vars: teststr: "/testdir/ansible/testfile" ###################################################################### #获取到一个windows路径字符串中的文件名,2.0版本以后的ansible可用 - debug: msg: "{{teststr | win_dirname}}" vars: teststr: 'D:\study\zsythink' ###################################################################### #将一个windows路径字符串中的盘符和路径分开,2.0版本以后的ansible可用 - debug: msg: "{{teststr | win_splitdrive}}" vars: teststr: 'D:\study\zsythink' #可以配合之前总结的过滤器一起使用,比如只获取到盘符,示例如下 #msg: "{{teststr | win_splitdrive | first}}" #可以配合之前总结的过滤器一起使用,比如只获取到路径,示例如下 #msg: "{{teststr | win_splitdrive | last}}" ###################################################################### #realpath过滤器可以获取软链接文件所指向的真正文件 - debug: msg: "{{ path | realpath }}" vars: path: "/testdir/ansible/testsoft" ###################################################################### #relpath过滤器可以获取到path对于“指定路径”来说的“相对路径” - debug: msg: "{{ path | relpath('/testdir/testdir') }}" vars: path: "/testdir/ansible" ###################################################################### #splitext过滤器可以将带有文件名后缀的路径从“.后缀”部分分开 - debug: msg: "{{ path | splitext }}" vars: path: "/etc/nginx/conf.d/test.conf" #可以配置之前总结的过滤器,获取到文件后缀 #msg: "{{ path | splitext | last}}" #可以配置之前总结的过滤器,获取到文件前缀名 #msg: "{{ path | splitext | first | basename}}" ###################################################################### #to_uuid过滤器能够为对应的字符串生成uuid - debug: msg: "{{ teststr | to_uuid }}" vars: teststr: "This is a test statement" ###################################################################### #bool过滤器可以根据字符串的内容返回bool值true或者false #字符串的内容为yes、1、True、true则返回布尔值true,字符串内容为其他内容则返回false - debug: msg: "{{ teststr | bool }}" vars: teststr: "1" #当和用户交互时,有可能需要用户从两个选项中选择一个,比如是否继续, #这时,将用户输入的字符串通过bool过滤器处理后得出布尔值,从而进行判断,比如如下用法 #- debug: # msg: "output when bool is true" # when: some_string_user_input | bool ###################################################################### #map过滤器可以从列表中获取到每个元素所共有的某个属性的值,并将这些值组成一个列表 #当列表中嵌套了列表,不能越级获取属性的值,也就是说只能获取直接子元素的共有属性值。 - vars: users: - name: tom age: 18 hobby: - Skateboard - VideoGame - name: jerry age: 20 hobby: - Music debug: msg: "{{ users | map(attribute='name') | list }}" #也可以组成一个字符串,用指定的字符隔开,比如分号 #msg: "{{ users | map(attribute='name') | join(';') }}" ###################################################################### #与python中的用法相同,两个日期类型相减能够算出两个日期间的时间差 #下例中,我们使用to_datatime过滤器将字符串类型转换成了日期了类型,并且算出了时间差 - debug: msg: '{{ ("2016-08-14 20:00:12"| to_datetime) - ("2012-12-25 19:00:00" | to_datetime) }}' #默认情况下,to_datatime转换的字符串的格式必须是“%Y-%m-%d %H:%M:%S” #如果对应的字符串不是这种格式,则需要在to_datetime中指定与字符串相同的时间格式,才能正确的转换为时间类型 - debug: msg: '{{ ("20160814"| to_datetime("%Y%m%d")) - ("2012-12-25 19:00:00" | to_datetime) }}' #如下方法可以获取到两个日期之间一共相差多少秒 - debug: msg: '{{ ( ("20160814"| to_datetime("%Y%m%d")) - ("20121225" | to_datetime("%Y%m%d")) ).total_seconds() }}' #如下方法可以获取到两个日期“时间位”相差多少秒,注意:日期位不会纳入对比计算范围 #也就是说,下例中的2016-08-14和2012-12-25不会纳入计算范围 #只是计算20:00:12与08:30:00相差多少秒 #如果想要算出连带日期的秒数差则使用total_seconds() - debug: msg: '{{ ( ("2016-08-14 20:00:12"| to_datetime) - ("2012-12-25 08:30:00" | to_datetime) ).seconds }}' #如下方法可以获取到两个日期“日期位”相差多少天,注意:时间位不会纳入对比计算范围 - debug: msg: '{{ ( ("2016-08-14 20:00:12"| to_datetime) - ("2012-12-25 08:30:00" | to_datetime) ).days }}' ###################################################################### #使用base64编码方式对字符串进行编码 - debug: msg: "{{ 'hello' | b64encode }}" #使用base64编码方式对字符串进行解码 - debug: msg: "{{ 'aGVsbG8=' | b64decode }}" ####################################################################### #使用sha1算法对字符串进行哈希 - debug: msg: "{{ '123456' | hash('sha1') }}" #使用md5算法对字符串进行哈希 - debug: msg: "{{ '123456' | hash('md5') }}" #获取到字符串的校验和,与md5哈希值一致 - debug: msg: "{{ '123456' | checksum }}" #使用blowfish算法对字符串进行哈希,注:部分系统支持 - debug: msg: "{{ '123456' | hash('blowfish') }}" #使用sha256算法对字符串进行哈希,哈希过程中会生成随机"盐",以便无法直接对比出原值 - debug: msg: "{{ '123456' | password_hash('sha256') }}" #使用sha256算法对字符串进行哈希,并使用指定的字符串作为"盐" - debug: msg: "{{ '123456' | password_hash('sha256','mysalt') }}" #使用sha512算法对字符串进行哈希,哈希过程中会生成随机"盐",以便无法直接对比出原值 - debug: msg: "{{ '123123' | password_hash('sha512') }}" #使用sha512算法对字符串进行哈希,并使用指定的字符串作为"盐" - debug: msg: "{{ '123123' | password_hash('sha512','ebzL.U5cjaHe55KK') }}" #如下方法可以幂等的为每个主机的密码生成对应哈希串 #有了之前总结的过滤器用法作为基础,你一定已经看懂了 - debug: msg: "{{ '123123' | password_hash('sha512', 65534|random(seed=inventory_hostname)|string) }}"

三十四、lookup插件#

  • 前文中的循环在本质上就是lookup插件
Copy
--- - hosts: test70 remote_user: root gather_facts: no tasks: - debug: msg: "index is {{item.0}} , value is {{item.1}}" with_indexed_items: ['a','b','c']

也可以写成

Copy
--- - hosts: test70 remote_user: root gather_facts: no tasks: - debug: msg: "index is {{item.0}} , value is {{item.1}}" loop: "{{ lookup('indexed_items',['a','b','c']) }}"
Copy
--- - hosts: test70 remote_user: root gather_facts: no vars: users: alice: female bob: male tasks: - debug: msg: "{{item.key}} is {{item.value}}" with_dict: "{{ users }}"

也可以用lookup写成

Copy
--- - hosts: test70 remote_user: root gather_facts: no vars: users: alice: female bob: male tasks: - debug: msg: "{{item.key}} is {{item.value}}" loop: "{{ lookup('dict',users) }}"
  • 可以使用命令行查看lookup插件是否可用,以及具体插件的用法
Copy
ansible-doc -t lookup -l ansible-doc -t lookup dict

三十五、循环(八)#

  • 2.5版本之前的ansible习惯使用"with_X"风格的关键字操作循环,2.6版本之后推荐使用loop关键字代替with_X风格的关键字

三十六、include#

  • 将重复性的任务提取到文件中并使用include进行引入,与代码中的函数类似

三十七、include(二)#

  • include_tasks可以代替include关键字
  • import_tasks也可以引入任务,不过是静态的(playbook被加载时就预处理了),include_tasks是动态的(playbook运行时实时处理)
  • import_playbook可以引入整个playbook

三十八、jinja2模板(一)#

  • 模板可以用来修改配置文件,通过template模块进行引用,模板中可以使用变量进行渲染
Copy
# cat temptest.yml --- - hosts: test70 remote_user: root gather_facts: no tasks: - yum: name: redis state: present - template: src: /testdir/ansible/redis.conf dest: /etc/redis.conf
  • jinja2模板中常用的基本语法:
    • {{ }} :用来装载表达式,比如变量、运算表达式、比较表达式等。
    • {% %} :用来装载控制语句,比如 if 控制结构,for循环控制结构。
    • {# #} :用来装载注释,模板文件被渲染后,注释不会包含在最终生成的文件中。

三十九、jinja2模板(二)#

  • 模板中的语法
    if控制语句
Copy
{% if 条件 %} ... {% endif %} {% if 条件 %} ... {% else %} ... {% endif %} {% if 条件一 %} ... {% elif 条件二 %} ... {% elif 条件N %} ... {% endif %}

类似三元表达式

Copy
{{ 'a' if 2>1 else 'b' }}

定义变量

Copy
{% set teststr='abc' %} {{ teststr }}

for循环

Copy
{% for 迭代变量 in 可迭代对象 %} {{ 迭代变量 }} {% endfor %}

四十、jinja2模板(三)#

  • 模板中的转义字符可以使用引号直接引起或者使用{{raw}}和{{endraw}}组合来括起来
  • 模板中可以定义类似函数的东西,叫做宏
Copy
{% macro testfunc() %} test string {% endmacro %} {{ testfunc() }}

四十一、jinja2模板(四)#

  • 模板中可以包含其他模板,使用标签
  • import可以引入其他文件中的宏
  • 集成模板使用

四十二、角色#

  • 使用ansible-galaxy命令快速创建角色、下载角色、管理角色

四十三、使用ansible-vault加密数据#

  • 使用命令对playbook文件进行加密
Copy
# 使用此命令加密 ansible-vault encrypt test.yml # 使用此命令解密执行 ansible-playbook --ask-vault-pass test.yml
  • ansible-vault其他命令,create、view、edit,rekey、encrypt_string

四十四、变量(七)#

  • group_vars和host_vars

四十五、常用技巧(一)#

  • 在ansible中使用python字符串的一些特性
    • 使用[]截取字符串
    • 使用+连接字符串
    • 使用*连续重复输出字符串
  • 使用任务委托delegate_to可以让某个任务指定在主机上执行
  • 让某个任务在ansible主机上执行,而不是受管主机上执行,connection: local
  • 让某个任务只执行一次(在ansible主机上的任务只执行一次),run_once: true
posted @   無花無酒鋤作田  阅读(95)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示
CONTENTS