Come spostare / rinominare un file usando un'attività Ansible su un sistema remoto


202

Come è possibile spostare / rinominare un file / directory usando un modulo Ansible su un sistema remoto? Non voglio usare il comando / le attività della shell e non voglio copiare il file dal sistema locale al sistema remoto.


Perché non vuoi usare il comando / shell?
Nick Urban,

4
Volevo solo sapere se esiste un modo senza usare le attività menzionate. Sembra che non ci sia altro modo al momento.
Christian Berendt,

1
Perché vuoi spostarlo in modo specifico invece di copiarlo? Sembra un'azione una tantum, piuttosto che un tipo di passo idempotente che garantisce lo stato del sistema.
Nick Urban,

2
Ho un file di configurazione di esempio incluso in un pacchetto RPM e voglio spostare questo file di configurazione di esempio.
Christian Berendt,

1
Al momento sto usando un link simbolico per fare riferimento al file. L'uso di get_url non è un'opzione per me perché il sistema non può raggiungere Internet.
Christian Berendt,

Risposte:


201

Il modulo file non copia i file sul sistema remoto. Il parametro src viene utilizzato solo dal modulo file durante la creazione di un collegamento simbolico a un file.

Se si desidera spostare / rinominare un file interamente su un sistema remoto, la soluzione migliore è utilizzare il modulo comandi per invocare il comando appropriato:

- name: Move foo to bar
  command: mv /path/to/foo /path/to/bar

Se vuoi essere sofisticato, puoi prima utilizzare il modulo stat per verificare che il foo esista effettivamente:

- name: stat foo
  stat: path=/path/to/foo
  register: foo_stat

- name: Move foo to bar
  command: mv /path/to/foo /path/to/bar
  when: foo_stat.stat.exists

3
Senza usare il modulo di comando, la tua unica altra scelta sarebbe quella di scrivere il tuo modulo personalizzato.
Bruce P,

2
Contrassegnato come risposta corretta perché questo è il modo attuale di copiare file remoti.
Christian Berendt,

11
A proposito di guardare prima di saltare: c'è qualche motivo per non usare l' removesopzione per il commandmodulo (documentata qui )? Sembra che questa opzione farebbe prima controllare Ansible.
Jim Witschey,

2
Ansible tiene traccia delle modifiche per avvisare il gestore, il che rende questa soluzione non ottimale.
boh

3
Non è necessario verificare manualmente l'esistenza del file se si utilizza removes: /path/to/fooe creates: /path/to/bar. @Fonant lo ha già menzionato come commento su un'altra risposta, ma poiché questa è quella accettata, desidero segnalarlo di nuovo.
Michael Trojanek,

218

Dalla versione 2.0 , nel modulo di copia è possibile utilizzare il remote_srcparametro.

Se Trueandrà al computer remoto / target per l'src.

- name: Copy files from foo to bar
  copy: remote_src=True src=/path/to/foo dest=/path/to/bar

Se si desidera spostare il file, è necessario eliminare il vecchio file con il modulo file

- name: Remove old files foo
  file: path=/path/to/foo state=absent

Dalla versione 2.8 il modulo di copia remote_src supporta la copia ricorsiva.


29
Piccola osservazione: "Attualmente remote_src non supporta la copia ricorsiva." tratto dal modulo ansible doc. Quindi, se si desidera copiare in modo ricorsivo, è comunque necessario il modulo shell / comando.
klaas,

23
Non capisco. Copiare e poi cancellare non equivale a spostarsi. Per uno, non è atomico. Per un altro, è più lento, specialmente per file di grandi dimensioni. Sono nuovo di Ansible, ma questo mi sembra davvero strano.
mlissner,

19
@alex quello che sto dicendo è che non può essere il modo giusto per farlo. Sto andando sopravento contro 50 voti positivi, ma è pazzesco. Un altro problema: le autorizzazioni e altri attributi non vengono mantenuti. Un altro: cosa succede se il file viene modificato durante la copia ?
mlissner,

2
@Hamish Downer e mlissner. Non ho detto che è la soluzione migliore per tutte le tue esigenze. Inoltre ho scritto che se vuoi copiare molti file non dovresti usare il modulo di copia. Leggi la domanda "Non voglio usare il comando / compiti della shell".
Alex,

7
@Alex questa è la seconda risposta più votata su una domanda sullo spostamento di file idempotente. La domanda non riguarda la copia. Esistono molti problemi con la copia anziché lo spostamento, pertanto questa risposta non è corretta. Quindi ottiene un downvote. L'etichetta su SO è di spiegare i voti negativi. Come notato altrove, l'opzione migliore finora ècommand: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Alec Wenzowski il

106

Ho trovato utile l'opzione di creazione nel modulo di comando. Cosa ne pensi di questo:

- name: Move foo to bar
  command: creates="path/to/bar" mv /path/to/foo /path/to/bar

Ho usato un approccio a 2 attività usando stat come suggerisce Bruce P. Ora faccio questo come un compito con crea. Penso che questo sia molto più chiaro.


60
O ancora meglio: command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Fonant,

8

Un'altra opzione che ha funzionato bene per me è l'utilizzo del modulo di sincronizzazione . Quindi rimuovere la directory originale utilizzando il modulo file.

Ecco un esempio dai documenti:

- synchronize:
    src: /first/absolute/path
    dest: /second/absolute/path
    archive: yes
  delegate_to: "{{ inventory_hostname }}"

Questo non funziona localmente in ogni caso perché destsi accede tramite SSH anche se la directory si trova sullo stesso computer.
Karl Richter,

5

Un altro modo per raggiungere questo obiettivo è l'utilizzo filedi state: hard.

Questo è un esempio che ho avuto modo di lavorare:

- name: Link source file to another destination
  file:
    src: /path/to/source/file
    path: /target/path/of/file
    state: hard

Testato solo su localhost (OSX), ma dovrebbe funzionare anche su Linux. Non posso dirlo per Windows.

Si noti che sono necessari percorsi assoluti. Altrimenti non mi permetterebbe di creare il collegamento. Inoltre, non è possibile attraversare i filesystem, quindi il funzionamento con qualsiasi supporto montato potrebbe non riuscire.

Il collegamento fisico è molto simile allo spostamento, se successivamente si rimuove il file di origine:

- name: Remove old file
  file:
    path: /path/to/source/file
    state: absent

Un altro vantaggio è che i cambiamenti persistono quando sei nel bel mezzo di una commedia. Quindi, se qualcuno cambia l'origine, qualsiasi modifica si riflette nel file di destinazione.

È possibile verificare il numero di collegamenti a un file tramite ls -l. Il numero di hardlink è mostrato accanto alla modalità (es. Rwxr-xr-x 2, quando un file ha 2 collegamenti).


2
Sfortunatamente, questo non funzionerà per una directory, in quanto i collegamenti non sono consentiti per le directory (((
Drew

1
Questa risposta presuppone il sistema di destinazione, in particolare che sia src che dest si trovano sulla stessa partizione. Questo potrebbe non essere vero e quindi questa risposta non dovrebbe essere utilizzata.
Mikky

4

Bruce non stava tentando di impostare la destinazione per verificare se spostare o meno il file se era già lì; si stava assicurando che il file da spostare esistesse effettivamente prima di tentare il mv.

Se il tuo interesse, come quello di Tom, è spostare solo se il file non esiste già, penso che dovremmo ancora integrare il controllo di Bruce nel mix:

- name: stat foo
  stat: path=/path/to/foo
  register: foo_stat

- name: Move foo to bar
  command: creates="path/to/bar" mv /path/to/foo /path/to/bar
  when: foo_stat.stat.exists

3

Questo è il modo in cui l'ho fatto funzionare per me:

  Tasks:
  - name: checking if the file 1 exists
     stat:      
      path: /path/to/foo abc.xts
     register: stat_result

  - name: moving file 1
    command: mv /path/to/foo abc.xts /tmp
    when: stat_result.stat.exists == True

il playbook sopra, controllerà se esiste il file abc.xts prima di spostare il file nella cartella tmp.


3
Non c'è bisogno di usare when: stat_result.stat.exists == True. Basta usare when: stat_result.stat.existsè abbastanza buono.
kuttumiah,

Di solito uso il == Trueperché faccio sempre qualcosa quando il file non viene trovato o == False.
eduprado,

Secondo la pagina di documentazione ufficiale dellastat exists proprietà del modulo restituisce un booleanvalore. Quindi, se lo metti, when: stat_result.stat.existsciò soddisferà la condizione se il file è presente, che è anche identico when: stat_result.stat.exists == Truema con più testi e controllo condizionale non necessario.
kuttumiah,

0

Questo può sembrare eccessivo, ma se vuoi evitare di usare il modulo di comando (cosa che faccio, perché usare il comando non è idempotente) puoi usare una combinazione di copia e non archivistica.

  1. Utilizzare tar per archiviare i file necessari. Se pensi al futuro, questo ha davvero senso. È possibile che si desideri una serie di file in una determinata directory. Crea quella directory con tutti i file e archiviali in un tar.
  2. Utilizzare il modulo unarchive. Quando lo fai, insieme alla destinazione: e remote_src: parola chiave, puoi posizionare tutti i tuoi file in una cartella temporanea per iniziare e quindi decomprimerli esattamente dove vuoi.

Non c'è idempotenza nell'archiviazione con tar
visit1985

0

Puoi farlo da -

Utilizzo del comando ad hoc

ansible all -m command -a" mv /path/to/foo /path/to/bar"

Oppure tu se vuoi farlo usando il playbook

- name: Move File foo to destination bar
  command: mv /path/to/foo /path/to/bar

0

So che è un vecchio argomento ANNI , ma mi sono frustrato e ho creato un ruolo per me stesso fare esattamente questo per un elenco arbitrario di file. Estendi come ritieni opportuno:

main.yml

- name: created destination directory
  file:
    path: /path/to/directory
    state: directory
    mode: '0750'
- include_tasks: move.yml
  loop:
    - file1
    - file2
    - file3

move.yml

- name: stat the file
  stat:
    path: {{ item }}
  register: my_file

- name: hard link the file into directory
  file:
    src: /original/path/to/{{ item }}
    dest: /path/to/directory/{{ item }}
    state: hard
  when: my_file.stat.exists

- name: Delete the original file
  file:
    path: /original/path/to/{{ item }}
    state: absent
  when: my_file.stat.exists

Si noti che il collegamento reale è preferibile alla copia qui, poiché preserva intrinsecamente la proprietà e le autorizzazioni (oltre a non consumare più spazio su disco per una seconda copia del file).


0

Su Windows: - name: Move old folder to backup win_command: "cmd.exe /c move /Y {{ sourcePath }} {{ destinationFolderPath }}"

Per rinominare utilizzare invece il comando rename o ren

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.