如何在Ansible中获取最高版本Worker文件并传递给script模块?
问题:自动选择版本号最高的Worker脚本执行
我在Ansible控制节点的scripts目录下有多个形如Worker1_0、Worker1_5、Worker2_1的文件,文件名中的数字对应版本号。需要编写一个Role,自动定位该目录下版本号最高的文件,并通过script模块在远程节点执行它。
已尝试的操作及问题
1. 查找匹配文件
使用find模块获取所有符合Worker*模式的文件:
- name: Find Worker find: paths: "{{ scripts_path }}" patterns: "Worker*" file_type: file register: worker delegate_to: localhost run_once: true
该任务成功返回了目标文件列表。
2. 整理并排序文件路径
尝试通过过滤器整理路径并排序:
- name: Show Output debug: msg: {{ worker | json_query('files[*].path') | sort | reverse }}
输出结果如下,看似完成了排序,但不确定该方式是否正确:
ok: [SERVER] => { "msg": [ "/srv/git/scripts/Worker3_8", "/srv/git/scripts/Worker3_5" ] }
3. 尝试执行最高版本脚本失败
使用with_first_found传递排序后的列表时报错:
- name: Execute Script on Remote server ansible.builtin.script: cmd: "{{ item }} " with_first_found: "{{ worker | json_query('files[*].path') | sort | reverse }}" register: script_output
错误信息:
FAILED! => {"msg": "No file was found when using first_found."}
解决方案
核心问题解析
- 字符串排序的局限性:直接用
sort | reverse是按字符串字典序排序,若版本号出现两位数(如Worker1_10),会出现Worker1_10排在Worker1_2之后的错误,因为字符串比较中"10"小于"2"。 with_first_found用法错误:该查找器默认在远程节点查找文件,而目标脚本位于控制节点,因此无法找到文件。
正确实现步骤
步骤1:按版本号数值排序文件
通过拆分文件名提取版本号,转换为整数后排序,确保数值排序逻辑正确:
- name: Sort Worker scripts by version number set_fact: sorted_worker_scripts: "{{ worker.files | sort( attribute='basename', key=lambda fname: [ int(fname.basename.split('_')[1]), int(fname.basename.split('_')[2].split('.')[0]) ], reverse=True ) }}" delegate_to: localhost run_once: true
注:这里假设文件名严格遵循WorkerX_Y格式,拆分出主版本X和次版本Y并转为整数排序。
步骤2:获取最新版本脚本路径
- name: Get path of latest Worker script set_fact: latest_worker_script: "{{ sorted_worker_scripts[0].path }}" delegate_to: localhost run_once: true
步骤3:在远程节点执行脚本
直接传入最新脚本路径到script模块:
- name: Execute latest Worker script on remote ansible.builtin.script: cmd: "{{ latest_worker_script }}" register: script_output
简化方案(适用于版本号无多位数场景)
如果可以确保版本号不会出现两位数导致的排序问题,可直接取排序后的第一个元素:
- name: Get latest Worker script path set_fact: latest_worker_script: "{{ worker | json_query('files[*].path') | sort | reverse | first }}" delegate_to: localhost run_once: true - name: Execute latest Worker script ansible.builtin.script: cmd: "{{ latest_worker_script }}" register: script_output
内容的提问来源于stack exchange,提问作者Luke
相关产品推荐
相关产品推荐

