Copie vários arquivos com o Ansible


104

Como posso copiar mais de um único arquivo em nós remotos por Ansible em uma tarefa?

Eu tentei duplicar a linha do módulo de cópia em minha tarefa para definir arquivos, mas ela apenas copia o primeiro arquivo.

Respostas:


131

Você pode usar o with_fileglobloop para isso:

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

3
Essa abordagem poderia me ajudar se eu tivesse todos os meus arquivos na mesma raiz para copiar na máquina remota, que tal ter alguns arquivos em vários diretórios. Por exemplo, quero copiar 3 arquivos de 3 diretórios diferentes
Marcos,

Ei, estou tentando mover todos os arquivos do meu, /roles/db/filesmas não consigo fazê-lo funcionar com este método. Eu tentei, with_fileglob: - /roles/db/file/* mas não consegui resolver o caminho
Batman

A grande desvantagem desse método é que ele nivela a estrutura do diretório.
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

É possível ter essa solução com o destconjunto como variável? { src: 'containerizers', dest: {{ containerizers }} }.
Gesias

2
@Gesias, sim. Na verdade, ambos os lados podem ser variáveis:{ src: '{{ source.var }}', dest: '{{ dest.var }}' }
ntwrkguru

16

Você pode usar with_together para esta finalidade:

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

Embora funcione, isso não é semanticamente limpo - existem opções mais limpas.
plesiv

11

Se você precisar de mais de um local, precisará de mais de uma tarefa. Uma tarefa de cópia pode copiar apenas de um local (incluindo vários arquivos) para outro no nó.

- 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/*

- nome: copiar arquivo1 cópia: src = / arquivo1 dest = / destino / arquivo1 - nome: copiar arquivo2 cópia: src = / arquivo2 dest = / destino / arquivo2
Marcar em

Depende. Mais simples e provavelmente mais limpo, mas pode ser feito usando estruturas de dados mais complexas, como uma lista de dicionários anônimos com dados de origem e destino, em loop com_itens. É o mesmo em qualquer idioma - você tem que fazer um julgamento. Há casos em que uma função de delegação é mais eficiente e sustentável do que uma longa série de instruções if de copiar / colar. Sou aquela aberração que prefere manter a parte concisa de um código bem estruturado do que uma lista longa e tediosa de diretivas quase idênticas, mas não presumo que todos concordem. Faça o que é sustentável para você.
Paul Hodges

8

Desde o Ansible 2.5, as with_*construções estão obsoletas e a loopsintaxe deve ser usada. Um exemplo prático simples:

- 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 }}"

apenas uma nota lateral que o findmódulo só funciona para ansible 2.x, mas não para ansible 1.x
Arbab Nazar

Corrigi sua resposta porque você mencionou stdout_linesno valor de retorno, mas não é aplicável para o findmódulo. Tem apenas files, examinede matchedcomo valores de retorno. Espero que ajude outros
Arbab Nazar

2
Alguém conseguiu fazer isso funcionar para copiar arquivos para nós remotos? findsó parece olhar para o sistema remoto, não permitindo pegar nada do nó de gerenciamento. Essas respostas, usando with_fileglob, parecem ser mais adequadas: stackoverflow.com/a/42290160/272387 , stackoverflow.com/a/36720342/272387 .
Richlv

4

Ou você pode usar 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
Uma boa resposta contém não apenas código, mas também algumas explicações ou referências de documentação.
Laurenz Albe de

Os módulos find, set_fact e copy são explicados na documentação ansible. Leia sobre filtros, também explicados na documentação do ansible se você quiser saber mais sobre esta seção (- "{{find_files.files | map (attribute'path ') | list}}")
Fredric Andersson

1

Você pode percorrer a variável com a lista de diretórios:

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

1

Use o seguinte código-fonte para copiar vários arquivos em sua máquina cliente.


 - 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

Nota:

Se você estiver passando vários caminhos usando a variável, então

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

Se você está passando o caminho usando uma variável para itens diferentes, então

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


0

copymódulo é uma ferramenta errada para copiar muitos arquivos e / ou estrutura de diretório, use o synchronizemódulo que usa rsynccomo backend. Lembre-se de que ele requer rsyncinstalação no controlador e no host de destino. É realmente poderoso, verifique a documentação do ansible .

Exemplo - copie arquivos do builddiretório (com subdiretórios) do controlador para o /var/www/htmldiretório no host de destino:

synchronize:
  src: ./my-static-web-page/build/
  dest: /var/www/html
  rsync_opts:
    - "--chmod=D2755,F644" # copy from windows - force permissions
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.