ansible卡在“gathering facts”主因是setup模块收集系统信息失败,需确认python版本、ssh配置并可禁用事实收集;shell模块不解析jinja2变量,应指定executable或改用shell模块;cron模块不重载服务且忽略path,须校验语法并显式指定user和完整路径;跨发行版需用package模块或条件判断os_family。

Ansible 执行任务卡在 “Gathering Facts” 不动
这是最常见的阻塞点,不是 Ansible 挂了,而是它默认会先 SSH 连上去跑 setup 模块收集目标主机的系统信息(比如 OS 版本、IP、磁盘、Python 路径等)。如果目标机 Python 缺失、SSH 延迟高、或防火墙拦截了某些探测行为,就会卡住甚至超时失败。
实操建议:
- 确认目标主机已安装 Python 3(
python3 --version),Ansible 2.10+ 默认要求 Python 3;若只有 Python 2,需在 inventory 中显式指定ansible_python_interpreter=/usr/bin/python2 - 跳过事实收集:在 playbook 顶层加
gather_facts: false,或 ad-hoc 命令加-m ping快速验证连通性(ansible all -m ping) - 检查 SSH 配置:确保
ControlPersist yes和ControlMaster auto开启,避免每次任务都新建连接;同时确认~/.ssh/config中没写错HostKeyAlgorithms导致握手失败
Shell 模块里变量不展开,{{ item }} 输出字面量
Ansible 的 shell 和 command 模块默认不经过 shell 解析器,所以 $PATH、$(date)、{{ item }} 这类都不会被替换——它们只是字符串参数,传给远程 /bin/sh -c 时还没被 Jinja2 渲染。
实操建议:
- 用
args:+executable: /bin/bash强制走 bash:- name: Run bash command with variable shell: echo "host: {{ inventory_hostname }}" args: executable: /bin/bash - 更安全的做法是改用
ansible.builtin.shell(显式声明)并配合vars:或loop:控制上下文,避免拼接字符串引发注入 - 如果只是想执行简单命令,优先用
command模块(更安全、无 shell 注入风险),把需要展开的内容提前用set_fact存成变量再引用
Cron 模块添加定时任务后不生效
Ansible 的 cron 模块只负责写入 /var/spool/cron/ 或 /etc/cron.d/,但不会 reload cron daemon,也不会校验语法是否合法。常见现象是文件写了,但 crond 没读取,或者环境变量缺失导致脚本找不到命令。
注意:请在linux环境下测试或生产使用 青鸟内测是一个移动应用分发系统,支持安卓苹果应用上传与下载,并且还能快捷封装网址为应用。应用内测分发:一键上传APP应用包,自动生成下载链接和二维码,方便用户内测下载。应用封装:一键即可生成app,无需写代码,可视化编辑、 直接拖拽组件制作页面的高效平台。工具箱:安卓证书生成、提取UDID、Plist文件在线制作、IOS封装、APP图标在线制作APP分发:
实操建议:
- 加
validate: 'crontab -t %s'参数让 Ansible 在写入前校验语法,避免非法格式写死 cron 表 - 明确指定
user:(如root),否则默认以当前连接用户写入,可能和预期不符;写入/etc/cron.d/时还必须带用户名字段,cron daemon 才认 - 注意 PATH:系统 crond 的默认 PATH 很窄(通常只有
/usr/bin:/bin),脚本中别直接写python3,换成/usr/bin/python3或在 crontab 条目开头加PATH=/usr/local/bin:/usr/bin:/bin
Playbook 在不同发行版上因包管理器报错
同一份 Playbook 在 CentOS 和 Ubuntu 上运行,yum 和 apt 模块不能混用,硬编码会导致失败。Ansible 不会自动识别 distro 并切换模块,得靠条件判断。
实操建议:
- 用
ansible_facts['distribution']或ansible_facts['os_family']做条件分支,例如:- name: Install nginx yum: name: nginx state: present when: ansible_facts['os_family'] == 'RedHat' - 优先使用抽象层模块如
package(Ansible 2.5+),它会根据ansible_facts['pkg_mgr']自动选apt/yum/dnf,但要注意旧版系统(如 CentOS 7)的pkg_mgr可能是yum,而 CentOS 8 是dnf,行为略有差异 - 避免在
vars:里硬写包名(如nginx_package: nginx),应按发行版覆盖:vars_files: [vars/RedHat.yml, vars/Debian.yml]
真正麻烦的从来不是写多少 task,而是每个模块背后隐含的执行上下文:Python 版本、shell 环境、cron 加载机制、包管理器状态——这些细节不会报错,但会让任务静默失败。









