set_fact 是 ansible 中用于运行时动态定义变量的模块,支持静态赋值、命令结果提取、条件逻辑及主机作用域控制,变量默认仅对当前主机生效。

Set_fact 是 Ansible 中用于在 Playbook 运行时动态定义变量的模块,它让变量值可以在任务执行过程中根据条件、命令结果或逻辑计算生成,而不是写死在 YAML 里。它特别适合需要“先查再用”“按需赋值”的场景,比如获取远程主机信息、拼接路径、判断服务状态后设置开关等。
基础用法:直接赋值或引用其他变量
最简单的用法是给一个新变量赋固定值或已有变量的值:
- 使用
set_fact:后跟键值对,如my_var: "hello" - 支持 Jinja2 表达式,可引用
hostvars、groups、inventory_hostname等内置变量
示例:
- name: 设置静态字符串
set_fact:
app_name: "nginx-web"
- name: 拼接主机名和环境 set_fact: full_id: "{{ inventory_hostname }}-{{ env }}"
结合命令结果动态赋值(常用)
常与 command、shell 或 stat 等模块配合,把执行结果存为变量供后续任务使用:
- 先用
shell获取输出,用register捕获结果 - 再用
set_fact提取stdout或判断逻辑并赋值
示例:检查某目录是否存在,并设标志位
- name: 检查 /opt/app 目录
stat:
path: /opt/app
register: app_dir_stat
name: 设置 exists 标志 set_fact: app_dir_exists: "{{ app_dir_stat.stat.exists | default(false) }}"
name: 仅当目录存在时启动服务 systemd: name: myapp state: started when: app_dir_exists
条件赋值与多分支逻辑
利用 Jinja2 的三元运算符或 selectattr 等过滤器,实现类似 if-else 的动态赋值:
"{{ 'prod' if env == 'production' else 'staging' }}"- 也可用
set_fact配合when实现多任务分支赋值
示例:根据系统类型设置不同软件包名
- name: 设置包名(CentOS vs Ubuntu)
set_fact:
pkg_name: "{{ 'httpd' if ansible_facts['os_family'] == 'RedHat' else 'apache2' }}"
- name: 安装 Web 服务 package: name: "{{ pkg_name }}" state: present
作用域注意:默认是 host\_vars,不可跨主机共享
set_fact 定义的变量默认只对当前主机生效(即存入 hostvars[inventory_hostname]),不会自动广播到其他主机:
- 若需在另一台主机上使用该变量,必须显式引用,如
{{ hostvars['web01'].app_version }} - 想全局可用?改用
vars(静态)、include_vars(文件加载)或自定义插件
示例:从 db 主机获取版本号,在 app 主机上使用
# 在 db 主机上设置
- name: 获取数据库版本
shell: psql --version | awk '{print $3}'
register: psql_ver_out
when: inventory_hostname == 'db01'
- name: 设置全局可见变量(不推荐,仅作说明) set_fact: global_db_version: "{{ psql_ver_out.stdout }}" when: inventory_hostname == 'db01'
在 app 主机上引用(需确保 db01 已执行过 set_fact)
- name: 显示 db 版本 debug: msg: "DB version is {{ hostvars['db01'].global_db_version }}" when: inventory_hostname == 'app01'











