Ansible - 检查是否存在多个目录 - 如果存在 运行 每个目录上的脚本 - 如何?

Ansible - Check if multiple directories exist - if so run a script on each directory - How?

我正在为我们的 Web 服务创建部署手册。每个网络服务都在自己的目录中,例如:

/webapps/service-one/
/webapps/service-two/
/webapps/service-three/

我想检查服务目录是否存在,如果存在,我想运行一个shell脚本来优雅地停止服务。目前,我可以使用 ignore_errors: yes.

完成此步骤
- name: Stop services
  with_items: services_to_stop
  shell: "/webapps/scripts/stopService.sh {{item}}"
  ignore_errors: yes

虽然这有效,但如果其中一个目录不存在或第一次部署服务,输出会非常混乱。我实际上想要这样的东西之一:

这个:

- name: Stop services
  with_items: services_to_stop
  shell: "/webapps/scripts/stopService.sh {{item}}"
  when: shell: [ -d /webapps/{{item}} ] 

或者这个:

- name: Stop services
  with_items: services_to_stop
  shell: "/webapps/scripts/stopService.sh {{item}}"
  stat: 
    path: /webapps/{{item}}
  register: path
  when: path.stat.exists == True

这将让您将现有目录名称的列表放入列表变量dir_names(使用recurse: no仅读取webapps下的第一级):

---

- hosts: localhost
  connection: local
  vars:
    dir_names: []

  tasks:
    - find:
        paths: "/webapps"
        file_type: directory
        recurse: no
      register: tmp_dirs
    - set_fact:  dir_names="{{ dir_names+ [item['path']] }}"
      no_log: True
      with_items:
        - "{{ tmp_dirs['files'] }}"

    - debug: var=dir_names

然后您可以通过 with_items 在 "Stop services" 任务中使用 dir_names。看起来你打算只使用 "webapps" 下的目录名称,所以你可能想使用 | basename jinja2 过滤器来获取它,所以像这样:

- name: Stop services
  with_items: "{{ dir_names }}"
  shell: "/webapps/scripts/stopService.sh {{item | basename }}"

我会先收集事实,然后只做必要的事情。

 - name: Check existing services
   stat:
     path: "/tmp/{{ item }}"
   with_items: "{{ services_to_stop }}"
   register: services_stat

 - name: Stop existing services
   with_items: "{{ services_stat.results | selectattr('stat.exists') | map(attribute='item') | list }}"
   shell: "/webapps/scripts/stopService.sh {{ item }}"

另请注意,with_items 中的裸变量自 Ansible 2.2 起不再起作用,因此您应该将它们模板化。