Ansible如何判断服务是否存在并跳过对应任务?
Ansible条件判断服务存在失效的解决方法
我有一个Ansible剧本,用来列出机器上已安装的Postgres、ElasticSearch、MongoDB、MySQL服务及其版本。想要添加条件,当服务不存在时跳过对应任务,但使用when: "'postgresql.service' in services"没生效。
现有服务扫描任务:
tasks: - name: Gather services service_facts: become: true - name: Filter services set_fact: services_app: "{{ services | dict2items | selectattr('value.state', 'match', 'running') | selectattr('value.source', 'match', service_mgr | string) | selectattr('value.name', 'search', (services_to_scan | join('|'))) | map(attribute='key') | list | default([]) }}"
Postgres版本检查任务:
- name: Check Postgresql shell: psql --version register: psql - name: debbuger la version Postgres debug: var=psql.stdout_lines when: "'postgresql.service' in services"
问题原因
原条件失效的核心是**service_facts收集的services变量是字典类型**,'postgresql.service' in services实际是检查该字符串是否是字典的键,但Ansible中字典的in操作符行为容易被误解;另外如果你的服务名不是精确的postgresql.service(比如部分系统是postgresql-15.service这类带版本的命名),也会导致判断失败。
解决方案
方案1:正确检查字典中的服务键
直接针对services字典的键进行判断,有两种可靠写法:
- 写法一:明确检查键是否存在于字典的键列表中
when: "'postgresql.service' in services.keys()"
- 写法二:利用
get方法判断服务是否存在(更严谨,避免键不存在时的潜在问题)
when: services.get('postgresql.service') is defined
方案2:复用已过滤的services_app列表
你已经通过set_fact生成了过滤后的services_app列表(仅包含运行中、对应服务管理器的目标服务),直接检查该服务是否在这个列表中即可:
- name: Check Postgresql command: psql --version # 推荐用command模块替代shell,更安全 register: psql when: "'postgresql.service' in services_app" - name: 打印Postgres版本 debug: var=psql.stdout_lines when: "'postgresql.service' in services_app"
额外提示
如果你的Postgres服务名不是固定的postgresql.service(比如不同版本会带后缀),可以调整services_to_scan变量,把postgres相关的关键词加入:
vars: services_to_scan: - postgres - elasticsearch - mongodb - mysql
这样selectattr('value.name', 'search', ...)会匹配所有名称包含postgres的服务,之后判断时也可以用模糊匹配:
when: services_app | select('search', 'postgres') | list | length > 0
内容的提问来源于stack exchange,提问作者Anass JARBAL
相关产品推荐
相关产品推荐

