Скопируйте несколько файлов с помощью Ansible


105

Как я могу скопировать более одного файла на удаленные узлы с помощью Ansible в задаче?

Я попытался продублировать строку модуля копирования в своей задаче для определения файлов, но она копирует только первый файл.

Ответы:


131

Для этого можно использовать with_fileglobцикл:

- copy:
    src: "{{ item }}"
    dest: /etc/fooapp/
    owner: root
    mode: 600
  with_fileglob:
    - /playbooks/files/fooapp/*

3
Этот подход мог бы помочь мне, если бы у меня были все мои файлы в одном корне для копирования на удаленный компьютер, как насчет того, чтобы некоторые файлы были в разных каталогах. Например, я хочу скопировать 3 файла из 3 разных директорий
Марк,

Эй, я пытаюсь переместить все файлы из своего, /roles/db/filesно не могу заставить его работать с этим методом. Я пробовал, with_fileglob: - /roles/db/file/* но путь не
Бэтмен

Большой недостаток этого метода в том, что он сглаживает структуру каталогов.
Quintin Par

115
- name: Your copy task
  copy: src={{ item.src }} dest={{ item.dest }}
  with_items:
    - { src: 'containerizers', dest: '/etc/mesos/containerizers' }
    - { src: 'another_file', dest: '/etc/somewhere' }
    - { src: 'dynamic', dest: '{{ var_path }}' }
  # more files here

Возможно ли это решение с destнабором в качестве переменной? { src: 'containerizers', dest: {{ containerizers }} }.
Gesias

2
@ Гесиас, да. На самом деле, обе стороны могут быть переменными:{ src: '{{ source.var }}', dest: '{{ dest.var }}' }
ntwrkguru

16

Для этого можно использовать with_toght:

- name: Copy multiple files to multiple directories
  copy: src={{ item.0 }} dest={{ item.1 }}
  with_together:
    - [ 'file1', 'file2', 'file3' ]
    - [ '/dir1/', '/dir2/', '/dir3/' ]

Хотя это работает, это семантически не чисто - есть более чистые варианты.
плесив

12

Если вам нужно более одного места, вам нужно более одной задачи. Одна задача копирования может копировать только из одного места (включая несколько файлов) в другое на узле.

- copy: src=/file1 dest=/destination/file1
- copy: src=/file2 dest=/destination/file2

# copy each file over that matches the given pattern
- copy: src={{ item }} dest=/destination/
  with_fileglob:
    - /files/*

- name: copy file1 copy: src = / file1 dest = / destination / file1 - name: copy file2 copy: src = / file2 dest = / destination / file2
Отметить

Смотря как. Проще и, вероятно, чище, но может быть выполнено с использованием более сложных структур данных, таких как список анонимных словарей с исходными и целевыми данными, зацикленный with_items. То же самое на любом языке - вы должны делать выводы. Бывают случаи, когда функция делегирования более эффективна и удобна в обслуживании, чем длинная серия операторов копирования / вставки if. Я тот урод, который предпочел бы сохранить лаконичный фрагмент хорошо структурированного кода, чем длинный и утомительный список почти идентичных директив, но я не думаю, что все согласны. Делайте то, что обслуживается за вас.
Пол Ходжес

8

Начиная с Ansible 2.5 with_*конструкции устарели , и loopследует использовать синтаксис. Простой практический пример:

- name: Copy CA files
  copy:
    src: '{{item}}'
    dest: '/etc/pki/ca-trust/source/anchors'
    owner: root
    group: root
    mode: 0644
  loop:
    - symantec-private.crt
    - verisignclass3g2.crt


7
- hosts: lnx
  tasks:
    - find: paths="/appl/scripts/inq" recurse=yes patterns="inq.Linux*"
      register: file_to_copy
    - copy: src={{ item.path }} dest=/usr/local/sbin/
      owner: root
      mode: 0775
      with_items: "{{ files_to_copy.files }}"

просто замечание, что findмодуль работает только для ansible 2.x, но не для ansible 1.x
Арбаб Назар

Я исправил ваш ответ, потому что вы указали stdout_linesв возвращаемом значении, но это не применимо для findмодуля. Это только files, examinedи в matchedкачестве возвращаемых значений. Надеюсь, что поможет другим
Арбаб Назар

2
Кто-нибудь смог заставить эту работу копировать файлы на удаленные узлы? findтолько кажется, что смотрит на удаленную систему, не давая ничего захватить с управляющего узла. Эти ответы с использованием with_fileglobкажутся более подходящими: stackoverflow.com/a/42290160/272387 , stackoverflow.com/a/36720342/272387 .
Richlv

4

Или вы можете использовать with_items:

- copy:
    src: "{{ item }}"
    dest: /etc/fooapp/
    owner: root
    mode: 600
  with_items:
    - dest_dir

3
- name: find inq.Linux*
  find:  paths="/appl/scripts/inq" recurse=yes patterns="inq.Linux*"
  register: find_files


- name: set fact
  set_fact:
    all_files:
      - "{{ find_files.files | map(attribute='path') | list }}"
  when: find_files > 0


- name: copy files
  copy:
    src: "{{ item }}"
    dest: /destination/
  with_items: "{{ all_files }}"
  when: find_files > 0

6
Хороший ответ содержит не только код, но также некоторые пояснения или ссылки на документацию.
Laurenz Albe

Модули find, set_fact и copy описаны в документации по ansible. Прочтите о фильтрах, также объясненных в документации по ansible, если вы хотите узнать больше об этом разделе (- "{{find_files.files | map (attribute'path ') | list}}")
Фредрик Андерссон

1

Вы можете перебирать переменную со списком каталогов:

- name: Copy files from several directories
  copy:
    src: "{{ item }}"
    dest: "/etc/fooapp/"
    owner: root
    mode: "0600"
  loop: "{{ files }}"
  vars:
    files:
      - "dir1/"
      - "dir2/"

1

Используйте следующий исходный код для копирования нескольких файлов на ваш клиентский компьютер.


 - name: Copy data to the client machine
   hosts: hostname
   become_method: sudo
   become_user: root
   become: true
   tasks: 
     # Copy twice as sometimes files get skipped (mostly only one file skipped from a folder if the folder does not exist)
     - name: Copy UFO-Server 
       copy:
         src: "source files path"
         dest: "destination file path"
         owner: root
         group: root
         mode: 0644
         backup: yes
       ignore_errors: true

Примечание:

Если вы передаете несколько путей с помощью переменной, тогда

SRC: "/ корень / {{элемент}}"

Если вы передаете путь, используя переменную для разных элементов, тогда

src: "/ root / {{item.source_path}}"


0

copymodule - неправильный инструмент для копирования многих файлов и / или структуры каталогов, используйте synchronizeвместо него модуль, который используется rsyncкак бэкэнд. Имейте в виду, это требует rsyncустановки как на контроллере, так и на целевом хосте. Это действительно мощно, проверьте доступную документацию .

Пример - копирование файлов из buildкаталога (с подкаталогами) контроллера в /var/www/htmlкаталог на целевом хосте:

synchronize:
  src: ./my-static-web-page/build/
  dest: /var/www/html
  rsync_opts:
    - "--chmod=D2755,F644" # copy from windows - force permissions
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.