一、为什么除了普通变量还要学 facts 和 register

前面的普通变量更多是人为定义的配置项,比如:

  • 路径
  • 用户名
  • IP 地址

但在真实自动化场景里,很多时候你还需要:

  • 动态获取目标主机自身的信息
  • 获取某条命令执行后的结果

这正是:

  • facts
  • register

存在的意义。

二、什么是 facts 变量

原始笔记对 facts 的定义是:

  • 运行剧本时,Ansible 会收集每个主机的基本信息
  • 这些信息形成的变量就叫 facts 变量

并且这些变量通常由:

  • setup 模块

来获取。

三、常见 facts 变量有哪些

原始笔记列出了一组很实用的 facts 变量:

  • ansible_hostname:主机名
  • ansible_memtotal_mb:总内存大小,单位 MB
  • ansible_processor_vcpus:CPU 虚拟核心数量
  • ansible_default_ipv4.address:默认网卡 IP
  • ansible_distribution:系统发行版名称
  • ansible_processor_cores:每个物理处理器的核心数量
  • ansible_date_time.date:当前系统日期

这些变量非常适合拿来做:

  • 主机信息展示
  • 条件判断
  • 模板渲染

四、如何把 facts 变量写进模板文件

原始笔记给了一个非常典型的实战:批量修改 /etc/motd,让用户登录时看到系统基本信息。

4.1 Playbook 示例

- hosts: all
  tasks:
    - name: 分发motd文件(使用template模块)
      template:
        src: templates/motd.j2
        dest: /etc/motd
        backup: yes

    - name: 分发motd文件(使用copy模块)
      copy:
        src: templates/motd.j2
        dest: /tmp/motd
        backup: yes

这里的关键点在于:

  • template 模块会解析模板里的变量
  • copy 模块只是单纯复制文件内容

4.2 模板文件 motd.j2

原始笔记中的模板示例如下:

#######################################
操作需谨慎,删根弹指间.
主机名: {{ ansible_hostname }}
ip地址: {{ ansible_default_ipv4.address }}
内存大小: {{ ansible_memtotal_mb }}
CPU数量: {{ ansible_processor_vcpus }}
核心总数: {{ ansible_processor_cores }}
发行版本: {{ ansible_distribution }}

这正好说明了 facts 变量最常见的应用场景:

  • 根据每台主机的真实信息动态渲染配置或提示文件

4.3 为什么 templatecopy 的结果不同

这个案例很适合帮助理解模块差异:

  • template:会渲染 Jinja2 变量
  • copy:不会渲染变量,只会原样复制

所以即使使用的是同一个源文件,最终写到 /etc/motd/tmp/motd 的结果也会不同。

五、什么是 register 注册变量

原始笔记对 register 的解释也很形象:

  • 本质上就是用来实现脚本里反引号的功能

例如脚本里常写:

ip=`hostname -I`

而在 Ansible 中,类似需求就可以通过 register 来完成。

六、register 变量怎么用

原始笔记给出的示例如下:

- hosts: all
  tasks:
    - name: get date
      shell: date +%F
      register: result

    - name: print result 变量内容
      debug:
        msg: |
          "register变量的标准输出是: {{ result.stdout }}"
          "register变量的标准错误是: {{ result.stderr }}"

这个例子体现了 register 的核心用法:

1、先执行命令 2、把执行结果保存到变量 3、再通过 debug 或后续任务引用结果

6.1 最常见的两个字段

原始笔记中重点用到的是:

  • result.stdout:标准输出
  • result.stderr:标准错误输出

这也是实际使用中最常见的两个字段。

七、msg 中的 | 是什么意思

原始笔记特别说明了一点:

  • msg: 中的 | 表示下面内容是多行

这个写法不只在 debug 模块中可以用,在其他需要多行文本的地方也经常会出现。

它的价值在于让多行输出更清晰,尤其适合:

  • 调试信息
  • 多行模板
  • 多段说明文字

八、facts 和 register 的区别怎么理解

可以这样记:

8.1 facts

  • 是 Ansible 自动收集到的主机基本信息
  • 更偏“主机自身属性”

8.2 register

  • 是任务执行后手动注册出来的结果
  • 更偏“命令或模块运行结果”

简单说:

  • facts 回答“这台机器本来是什么样”
  • register 回答“刚才执行完这一步得到了什么”

九、原始笔记里的变量总结很值得记住

原始笔记最后对变量来源做了总结,重点包括:

  • 在剧本文件中定义
  • 根据主机清单分组定义变量
  • register 变量
  • inventory 变量
  • 命令行变量
  • facts 变量

如果从实战优先级来看,最值得先掌握的是:

  • vars
  • group_vars
  • facts
  • register

十、小结

Ansible 变量学习到这一步,最值得真正掌握的内容有:

  • facts 变量是什么、能拿到哪些主机信息
  • template 模块如何配合 facts 渲染模板
  • register 如何获取命令执行结果
  • stdoutstderr 怎么取值
  • 多行 msg| 怎么用

当这些高级变量能力掌握之后,你写的剧本就不再只是“固定执行几个动作”,而是开始具备动态感知环境和处理结果的能力了。