Ansible 2.9.27 批量复制文件与权限设置实战指南

Ansible 2.9.27 批量复制文件与权限设置实战指南 简介Ansible 2.9.27是面向Linux运维工程师的开源自动化工具采用无代理架构通过SSH与目标主机通信无需在每台服务器上安装额外客户端特别适合CentOS 7/RHEL 7等企业级Linux发行版的大规模运维场景。深入掌握Ansible的模块化设计和Playbooks语法可帮助企业实现从系统配置、软件部署到服务编排的全流程自动化。该资源包共29个文件大小19.29MB其中22个rpm安装包完整覆盖Ansible主程序及python-jinja2、paramiko、PyYAML等核心依赖且均面向el7平台构建另有3个gz、3个bz2和1个xml文件构成仓库元数据可支持离线安装或配置本地yum源。目前已有632人学习下载。借助本包用户能快速搭建可用的Ansible控制端并通过Playbooks实现配置管理、软件分发、服务控制、模板渲染等自动化任务涵盖系统初始化、中间件部署到应用版本更新的常见需求显著减少重复劳动与人为失误是运维人员提升效率的实用工具。 最近把一批老服务器纳入统一管理选型这事我没犹豫太久直接定了 ansible-2.9.27。这个版本在运维圈子里属于“存量大户”不少团队到现在生产环境还在用它。如果你刚开始接触 ansible或者正在部署接管历史环境希望快速把批量复制文件、批量授权这类操作跑起来那这篇内容应该能帮你少踩不少坑。我在这台控制端上完成安装后用ansible --version确认版本号再把十几台节点一次性加入清单接着就是日常的批量分发和权限管理。整个过程里遇到的坑不少但基本都是老版本特有的“传统艺能”只要搞懂原理就很好避。下面我把整个实操流程、参数拆解和排错经验都写出来。1. 项目整体设计与思路拆解1.1 为什么选 2.9.27 而不是新版本我先解释一下版本背景。Ansible 从 2.10 开始做了架构拆分变成ansible-core加一堆collections集合包的形式。这意味着你装完 ansible 之后还要单独安装各个模块的集合包比如community.general、ansible.posix这些。很多老 playbook 里直接用copy:、command:模块的写法在新版本里虽然还能用但运行时会提示你补全ansible.builtin.copy这种带前缀的写法或者要求你提前把对应集合装好。2.9.27 是 2.9 分支的最后一个修复版本也是模块拆分的“前夜版本”。它最大的特点是控制端 Python 2.7 或 3.5 都能跑对老机器很友好受控端只需要 Python 2.6 或 3.5内网一堆 CentOS 6、7 的老机器没压力所有常用模块都内置在 ansible 本体里不需要额外拉集合包离线部署极其简单一个 pip 包就能搞定全部功能我曾经在一个只有内网的环境里部署新版本 ansible 装完还要想办法把一堆 collection 传进去而 2.9.27 只需要一个 wheel 包。这一条就足够让我在历史环境里坚持用这个版本。1.2 适用场景和影响范围如果你的环境属于下面几种情况2.9.27 非常适合公司内部有大量存量服务器操作系统版本偏老Python 环境混杂没有外网内网无法轻松安装 collection 包已经积累了一批老 playbook改造成新架构的模块前缀成本高团队主要用到 copy、command、shell、service、cron、yum 这些基础模块不需要新特性选择 2.9.27 的影响范围也需要想清楚你放弃了新版本里的 execution environments、更细粒度的集合管理、更严格的校验机制但换来的是稳定和兼容。对于“批量复制文件、批量授权、批量执行命令”这类日常操作新特性基本用不上所以这个取舍很值。2. 安装部署从零到能跑的通关步骤2.1 安装方式选型根据网络环境不同我整理了三种安装方式。安装方式适用场景命令示例说明pip 安装控制端能访问外网python3 -m pip install ansible2.9.27最推荐版本可控系统源安装内网镜像源已同步yum install ansible / apt install ansible注意源里版本可能不是 2.9.27离线安装完全隔离的内网见下方步骤需要提前在有网机器下载离线安装的具体步骤我在实际项目中用过# 在有外网的机器上 python3 -m pip download ansible2.9.27 -d ./ansible-offline # 把 ansible-offline 目录拷到内网 python3 -m pip install --no-index --find-links./ansible-offline ansible2.9.27安装完成后验证一下确保环境没问题ansible --version你会看到类似ansible 2.9.27的输出同时会显示当前使用的 Python 版本和配置文件路径。这里有一步容易忽略如果你用了python3 -m pip install那后续执行ansible命令时也要确保用的是同一个 Python 环境。实测中经常有人前面用pip3 install装了后面却用ansible命令时发现报模块找不到多半是环境变量指向了另一个 Python。2.2 配置清单与 SSH 免密登录Ansible 用一份 inventory 清单文件来管理节点默认路径是/etc/ansible/hosts。我的习惯是先在/etc/ansible/hosts里分组这样后续操作可以只针对某一组执行而不是每次都对所有节点开炮。[web] 192.168.1.10 192.168.1.11 [db] 192.168.2.10 [all:vars] ansible_userroot ansible_ssh_private_key_file/root/.ssh/id_rsa ansible_python_interpreter/usr/bin/python3配置好清单之后下一步就是 SSH 免密登录。Ansible 本质上是通过 SSH 执行命令所以免密配置是第一步。先生成密钥再把公钥分发到各个节点ssh-keygen -t rsa -N ssh-copy-id -i ~/.ssh/id_rsa.pub root192.168.1.10 ssh-copy-id -i ~/.ssh/id_rsa.pub root192.168.1.11节点多的时候一条条ssh-copy-id比较烦但如果你的机器还能用密码登录可以先把ansible_ssh_pass临时写进 hosts 里然后通过 Ansible 自己分发公钥。这里建议临时写完公钥分发后立刻把密码配置删掉避免敏感信息留在明文文件里。免密配好后验证连通性ansible all -m ping注意这里-m ping调用的是 Ansible 的 ping 模块用来测试控制端能否通过 SSH 正常执行 Python 命令不是网络层的 ICMP ping。返回 pong 就代表链路正常。如果目标机器没有/usr/bin/python3可以在 hosts 里把ansible_python_interpreter指到实际路径比如/usr/bin/python。这个参数在混用 Python 2 和 Python 3 的环境里非常实用。3. 核心实操复制文件到所有节点并授权 7773.1 copy 模块参数拆解手工运维最常见的需求就是“把某个文件复制到所有节点并赋予指定权限”。Ansible 的 copy 模块就是干这个的。先来看它最核心的参数参数作用使用建议src控制端本地源文件路径相对路径或绝对路径均可dest目标节点上的绝对路径必须是绝对路径mode目标文件权限建议写0777并加引号或写符号模式owner文件属主需要 root 或 sudo 权限group文件属组需要 root 或 sudo 权限backup覆盖前是否备份设为 yes 时有风险更稳妥force同名同内容是否强制覆盖默认 yes内容不一致时覆盖remote_src源文件是否已在目标节点上选 yes 时不再从控制端传输content直接写入字符串内容适合小文件不用单独准备源文件这里有一个非常重要的细节mode参数要加引号。在 YAML 里直接写mode: 0777会被解析成八进制整数而不是字符串传参给模块时类型不一致轻则警告重则权限设不上去。写成mode: 0777或者mode: urwx,grwx,orwx都是安全写法。我后来养成了写符号模式的习惯语义更清晰也不怕 YAML 解析问题。3.2 命令行批量分发与授权先看一条最简单的批量分发命令这也是我日常排查问题时的“三板斧”ansible all -m copy -a src/data/app.tar.gz dest/data/app.tar.gz mode0777 ownerroot grouproot这条命令会把控制端/data/app.tar.gz复制到所有节点的/data/app.tar.gz并设置属主 root、属组 root、权限 777。-m copy指定模块-a后面跟模块参数写成keyvalue的键值对格式。如果节点数量多建议加上-f参数提高并行度默认 forks 是 5也就是同时只操作 5 台机器。我有一次给 30 台机器推文件忘了加-f硬生生等了一分多钟加上-f 20之后直接 10 秒内跑完。ansible all -m copy -a src/data/app.tar.gz dest/data/app.tar.gz mode0777 -f 20分发完成后验证一下所有节点的文件权限ansible all -m command -a stat -c %a %n /data/app.tar.gz每条输出都会显示类似777 /data/app.tar.gz一眼就能确认有没有成功。这个验证方式比ls -l更适合脚本化处理建议收藏。3.3 Playbook 方式的完整示例命令行适合临时跑一次但如果这个操作要反复执行或者和其他配置动作组合在一起写成一个 playbook 更合理。下面是我在项目里实际用过的写法--- - name: 批量分发脚本并授权 hosts: all gather_facts: false tasks: - name: 复制清理脚本到 /data 目录 copy: src: /data/clean.sh dest: /data/clean.sh owner: root group: root mode: urwx,grwx,orwx - name: 确认文件已存在 command: ls -l /data/clean.sh register: result - name: 打印验证结果 debug: var: result.stdout执行方式ansible-playbook -i /etc/ansible/hosts copy-and-chmod.yml这里有个细节值得说明如果你要复制的是目录src路径结尾是否带斜杠效果完全不同。以/data/conf结尾会把conf目录本身复制到目标路径下最终是/data/conf/以/data/conf/结尾只会把conf目录里面的内容复制过去。我见过不少新手在这里栽跟头复制完发现目录结构多了一层或者少了一层还以为是模块 bug。另外2.9.27 的 copy 模块在复制目录时mode参数只会影响已存在的文件不会自动修正目录里已有文件的权限。如果需要批量修正已有文件的权限最稳的方式是用 file 模块再扫一遍- name: 批量修正目录下所有文件权限 file: path: /data/conf mode: 0777 recurse: yes4. 常见问题与排查技巧实录4.1 SSH 连接失败和 Host Key 校验新手第一次跑ansible all -m ping时最常遇到的报错是FAILED! {msg: Failed to connect to the host via ssh: Host key verification failed.}原因很简单目标主机公钥没有加入控制端的known_hosts文件。对于第一次连接SSH 默认会询问是否信任而 Ansible 不会交互式等待所以直接失败。解决办法有两种看你的安全要求选在ansible.cfg里设置host_key_checking False适合内部可信网络用ssh-keyscan提前把主机公钥批量加入 known_hostsssh-keyscan 192.168.1.10 192.168.1.11 192.168.2.10 ~/.ssh/known_hosts如果你同时管理很多台机器我建议维护一份ansible.cfg它本身有优先级当前目录下的配置 用户家目录~/.ansible.cfg/etc/ansible/ansible.cfg。我的基础配置长这样[defaults] host_key_checking False inventory /etc/ansible/hosts forks 20 log_path /var/log/ansible.log其中log_path一定记得开。跑完一遍 playbook 后如果哪个节点出了问题直接查这个日志比在终端里翻输出要清晰得多。4.2 Python 解释器与 sudo 权限的问题2.9.27 对受控端的 Python 要求不算高但前提是受控端得有 Python。最小化安装的 CentOS 有时候连 Python 都不会默认装上此时你执行任何模块都会报/bin/sh: /usr/bin/python: No such file or directory解决办法是确认受控端 Python 的真实路径然后在 hosts 里指定[all:vars] ansible_python_interpreter/usr/bin/python3还有一类常见问题与 sudo 有关。Ansible 默认通过 root 用户连接如果你的ansible_user不是 root而是普通用户那执行需要提权的任务时会在后台调 sudo。如果系统要求输入密码就会报sudo: a password is required解决方式要么在受控端配置 sudo 免密要么在执行命令时加-K参数并在提示时输入 sudo 密码ansible all -m copy -a src/data/app.tar.gz dest/data/app.tar.gz mode0777 -u ops -K4.3 777 权限的坑和副作用这是我在实际使用中踩得最深的一个坑。copy 模块在目标文件已经存在、且内容和源文件一致时不会重新设置权限。也就是说如果你第一次用mode0777复制过去没问题但文件内容完全没变时哪怕你第二次把 mode 改成0755再跑一遍 playbook权限也不会变。看起来像是“命令没生效”其实是因为 copy 模块认为文件无需变更跳过了整个任务。解决办法有两条先用file模块单独设置权限它每次都会执行- name: 强制修正权限 file: path: /data/clean.sh mode: 0777或者先删除远端文件再重新复制这个方法如果你在跑定时任务最好别用中间有短暂的时间窗口文件不存在。关于mode: 0777还要多提醒一句777 权限意味着所有用户可读、可写、可执行。在服务器上赋予一个脚本 777 权限等于把执行权交给了系统上的任何账号如果这台机器同时跑着 Nginx 或者 Java 服务被入侵的风险会明显上升。我真的见过有人把配置文件夹直接 777导致网站源码差点被篡改的事。生产环境建议能不用 777 就不用用 755 或者 750 都行只有临时共享目录才考虑 777。碰到权限相关的问题时加-v参数能让你看到更详细的执行日志ansible-playbook -v copy-and-chmod.yml最多可以加到-vvvv会输出 SSH 底层执行细节。另外一个很实用的排查方式是加--check先干跑一遍看看哪些任务会执行、哪些是幂等的不会真正改动目标节点ansible-playbook --check copy-and-chmod.yml我在批量操作前特别是涉及几百台机器的时候都会先--check过一遍确认没有误操作再正式执行。虽然不能百分百模拟所有情况但至少能提前发现明显的路径错误和变量引用问题。最后再分享一个小技巧。跑 playbook 时习惯性地给每个任务写清晰易懂的 name比如“复制清理脚本到 /data 目录”后面看日志时会清楚很多。有一次我在凌晨排查问题面对一堆默认的 task 名完全不知道哪一步在干什么后来就强迫团队里所有人都写 name。这种细节看起来不起眼实际操作中能帮你省下大量排查时间。如果你也是接管的存量环境2.9.27 完全够用不用被新版本迭代带着走。先把控制端装好清单配起来再把复制文件和权限设置这两个操作熟到条件反射日常 80% 的批量运维需求就都能覆盖了。本文还有配套的精品资源点击获取