ansible 如果未定义变量,设置默认变量
参考最后一行name
的实现, 如果my_variable
变量没有定义就会通过default()
方法设置一个默认值
- name: Create user
user:
name: "{{ my_variable | default('这里设置默认值') }}"
参考: https://www.jianshu.com/p/b9a788788a51
ansible 查找文件列表及过滤匹配
参考: https://docs.ansible.com/ansible/latest/collections/ansible/builtin/find_module.html
- name: Recursively find /tmp files older than 2 days
find:
paths: /tmp
age: 2d
recurse: yes
- name: Recursively find /tmp files older than 4 weeks and equal or greater than 1 megabyte
find:
paths: /tmp
age: 4w
size: 1m
recurse: yes
- name: Recursively find /var/tmp files with last access time greater than 3600 seconds
find:
paths: /var/tmp
age: 3600
age_stamp: atime
recurse: yes
- name: Find /var/log files equal or greater than 10 megabytes ending with .old or .log.gz
find:
paths: /var/log
patterns: '*.old,*.log.gz'
size: 10m
# Note that YAML double quotes require escaping backslashes but yaml single quotes do not.
- name: Find /var/log files equal or greater than 10 megabytes ending with .old or .log.gz via regex
find:
paths: /var/log
patterns: "^.*?\\.(?:old|log\\.gz)$"
size: 10m
use_regex: yes
- name: Find /var/log all directories, exclude nginx and mysql
find:
paths: /var/log
recurse: no
file_type: directory
excludes: 'nginx,mysql'
# When using patterns that contain a comma, make sure they are formatted as lists to avoid splitting the pattern
- name: Use a single pattern that contains a comma formatted as a list
find:
paths: /var/log
file_type: file
use_regex: yes
patterns: ['^_[0-9]{2,4}_.*.log$']
- name: Use multiple patterns that contain a comma formatted as a YAML list
find:
paths: /var/log
file_type: file
use_regex: yes
patterns:
- '^_[0-9]{2,4}_.*.log$'
- '^[a-z]{1,5}_.*log$'
删除文件目录及文件
- name: Clean artifact path
file:
state: absent
path: "{{ artifact_path }}/"
注意这也会删除目录
将变量列表全部转换成大写
-
将
ansible_interfaces
的值转换成大写的列表格式- hosts: localhost tasks: - name: print interfaces debug: msg: "{{ ansible_interfaces | map('upper') | list }}"
-
, 输出如下
TASK [print interfaces] *************************************************** ok: [localhost] { "msg": [ "DOCKER0", "LO", "VETH3E8C318", "WLAN0", "DOCKERCON", "ETH0", "VETHE2459C9" ] }
原文参考: https://www.tailored.cloud/devops/how-to-filter-and-map-lists-in-ansible
map
方法 还支持其他更多功能, 详情见: https://jinja.palletsprojects.com/en/2.10.x/templates/#map
-
例如: 实现获取
/tmp
下的目录列表,map(attribute='path')
用于获取files
对象path
对应的值- hosts: localhost tasks: - name: 获取目录列表 find: paths: "/tmp" recurse: no file_type: directory register: dirObjectList - name: 设置目录列表变量 set_fact: dirList: "{{ dirObjectList.files | map(attribute='path') | list }}" - name: 显示目录列表 debug: msg: "{{ dirList}}"
显示如下:
TASK [显示目录列表] ******************************************************************************************************************************************** ok: [localhost] => { "msg": [ "/tmp/undo", "/tmp/upgrade" ] }
在tasks中使用交互变量
-
利用
pause
实现在tasks中读取交互变量- hosts: localhost tasks: - pause: prompt: "Please enter the value for kernel.shmmax " echo: yes register: result - set_fact: shmmax: "{{ result.user_input }}" - debug: var: shmmax
-
需要注意的是下面这种用法是错误的, 会报语法错误
- name: shmmax prompt: " Please enter the value for kernel.shmmax " private: false
参考: https://serverfault.com/questions/969121/ansible-prompt-a-variable-in-a-task
使用变量作为数组下标
- 例如
{{nics[num].ip}}
是获取nics
数组下标为num
变量的值
参考: https://groups.google.com/g/ansible-project/c/wDSJZ72KiFo?pli=1# ansible-playbook test.yml --extra-vars "num=0" [SNIP] TASK: [Static IP Case - Find out Static Overlay IP] *************************** fatal: [127.0.0.1] => One or more undefined variables: 'list object' has no attribute u'0' # cat nics.yml --- nics: - {type: 'static', ip: '10.3.5.4'} - {type: 'dhcp'} - {type: 'static', ip: '10.3.5.5'} # cat test.yml - hosts: 127.0.0.1 vars_files: - "nics.yml" tasks: # Static IP Case: Find out the Overlay IP - name: Static IP Case - Find out Static Overlay IP set_fact: cvmip: "{{nics[num].ip}}" when: nics[num|int].type == "static" - name: Write Overlay IP to file shell: echo {{cvmip}} >> /tmp/staticip.txt when: nics[num|int].type == "static"
Jinja2在ansible中操作变量
-
变量赋值
{% set name='xx' %}
-
局部变量
{% with foo = 42 %} {{ foo }} {% endwith %}
-
变量类型转换
{% set node = "prometheus-"+ loop.index | string %}
-
if/else/elif/endif
{% if foo | bool %} ... {% elif not foo1 %} ... {% else %} ... {% endif %}
-
遍历list
{% for user in users %} {{ user.username | e }} {% endfor %}
-
遍历字典
{% for key, value in my_dict.iteritems() %} {{ key|e }} {{ value|e }} {% endfor %}
参考: https://blog.csdn.net/weixin_42119008/article/details/109345221
传递变量到include_tasks 或import_tasks
tasks:
- import_tasks: wordpress.yml
vars:
wp_user: timmy
- import_tasks: wordpress.yml
vars:
wp_user: alice
- import_tasks: wordpress.yml
vars:
wp_user: bob
-
import_tasks: 静态加载,也就是 playbook 在运行一开始解析的时候,加载子任务中全部变量。
-
include_tasks: 动态加载,就是在执行到该子任务的时候,才会加载该子任务中全部变量。
-
import_tasks 调用的子任务文件名称也就不可以使用变量,但是 include_tasks 调用的子任务名称则可以加变量。
-
import_tasks 会调用子任务中的所有 tag,使用 –list-tags 参数时也能看到,但是 include_tasks 调用的子任务中如果定义了tag,则不会生效。
参考:
- https://blog.51cto.com/liubin0505star/2572443
- https://docs.ansible.com/ansible/2.9/user_guide/playbooks_variables.html#ansible-variable-precedence
字符串去掉空格并比较
-
使用和python的strip一样
{{ string | trim }} == string.strip()
-
列表去空格
"{{ runconfserafter.stdout_lines | map('trim') | list }}"
参考:
生成指定范围内的整数列表
- 例如
user1
到user20
- set_fact:
users: "{{ users | default([]) + ['user%s' | format(item)] }}"
loop: "{{ range(1, 21) | list }}"
- 输出
{
"users": [
"user1",
"user2",
"user3",
"user4",
"user5",
"user6",
"user7",
"user8",
"user9",
"user10",
"user11",
"user12",
"user13",
"user14",
"user15",
"user16",
"user17",
"user18",
"user19",
"user20"
]
}
列表长度加一
- name: 测试列表
hosts: localhost
dirList: ["一","二","三","四","五"]
tasks:
- name: 遍历输出
debug:
msg: "{{item}}"
loop: "{{ range(1, (dirList|length|int + 1) ) | list }} "
- 输出:
TASK [遍历输出] *****************************************************
ok: [localhost] => (item=1) => {
"msg": 1
}
ok: [localhost] => (item=2) => {
"msg": 2
}
ok: [localhost] => (item=3) => {
"msg": 3
}
ok: [localhost] => (item=4) => {
"msg": 4
}
ok: [localhost] => (item=5) => {
"msg": 5
}
Ansible如何为每个主机顺序执行剧本
加上--forks=1
指定要使用的并行进程数(默认= 5) , 剧本中还可以通过strategy
策略来控制并行模式,
共有3种策略:linear 线性(默认),serial 串行 和 free(最快)
参考:
https://stackoverflow.com/questions/27315469/ansible-how-to-sequentially-execute-playbook-for-each-host
https://docs.ansible.com/ansible/latest/user_guide/playbooks_strategies.html#selecting-a-strategy