Verschieben / Umbenennen einer Datei mithilfe einer Ansible-Aufgabe auf einem Remote-System

202

Wie ist es möglich, eine Datei / ein Verzeichnis mit einem Ansible-Modul auf einem Remote-System zu verschieben / umzubenennen? Ich möchte die Befehls- / Shell-Aufgaben nicht verwenden und die Datei nicht vom lokalen System auf das Remote-System kopieren.

Christian Berendt
quelle
Warum möchten Sie nicht command / shell verwenden?
Nick Urban
4
Ich wollte nur wissen, ob es einen Weg gibt, ohne die genannten Aufgaben zu nutzen. Es sieht so aus, als gäbe es im Moment keinen anderen Weg.
Christian Berendt
1
Warum möchten Sie es gezielt verschieben, anstatt es zu kopieren? Das scheint eher eine einmalige Aktion zu sein als ein idempotenter Schritt, der den Zustand des Systems sicherstellt.
Nick Urban
2
Ich habe eine Beispielkonfigurationsdatei in einem RPM-Paket und möchte diese Beispielkonfigurationsdatei verschieben.
Christian Berendt
1
Im Moment verwende ich einen Symlink, um auf die Datei zu verweisen. Die Verwendung von get_url ist für mich keine Option, da das System das Internet nicht erreichen kann.
Christian Berendt

Antworten:

201

Das Dateimodul kopiert keine Dateien auf dem Remote-System. Der Parameter src wird vom Dateimodul nur verwendet, wenn ein Symlink zu einer Datei erstellt wird.

Wenn Sie eine Datei vollständig auf einem Remote-System verschieben / umbenennen möchten, verwenden Sie am besten das Befehlsmodul, um einfach den entsprechenden Befehl aufzurufen:

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

Wenn Sie Lust haben, können Sie zuerst das stat-Modul verwenden, um zu überprüfen, ob foo tatsächlich existiert:

- 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
Bruce P.
quelle
3
Ohne die Verwendung des Befehlsmoduls besteht Ihre einzige andere Möglichkeit darin, ein eigenes benutzerdefiniertes Modul zu schreiben.
Bruce P
2
Als richtige Antwort markiert, da dies die aktuelle Methode zum Kopieren von Remote-Dateien ist.
Christian Berendt
11
Was das Schauen betrifft, bevor Sie springen: Gibt es einen Grund, die removesOption für das commandModul ( hier dokumentiert ) nicht zu verwenden? Es scheint, dass diese Option Ansible zuerst prüfen lassen würde.
Jim Witschey
2
Ansible verfolgt Änderungen, um den Handler zu benachrichtigen, wodurch diese Lösung nicht optimal ist.
Boh
3
Sie müssen nicht manuell prüfen, ob die Datei vorhanden ist, wenn Sie removes: /path/to/foound verwenden creates: /path/to/bar. @Fonant hat dies bereits als Kommentar zu einer anderen Antwort erwähnt, aber da dies die akzeptierte ist, möchte ich noch einmal darauf hinweisen.
Michael Trojanek
218

Ab Version 2.0 , in Kopiermodul können Sie verwenden remote_srcParameter.

Wenn Truees für den src an den Remote- / Zielcomputer geht.

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

Wenn Sie eine Datei verschieben möchten, müssen Sie die alte Datei mit dem Dateimodul löschen

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

Ab Version 2.8 Kopiermodul remote_src unterstützt rekursive Kopieren.

Alex
quelle
29
Kleine Bemerkung: "Derzeit unterstützt remote_src kein rekursives Kopieren." entnommen aus dem ansible Modul doc. Wenn Sie also rekursiv kopieren möchten, benötigen Sie weiterhin das Shell- / Befehlsmodul.
Klaas
23
Ich verstehe nicht. Kopieren und Löschen ist nicht dasselbe wie Verschieben. Zum einen ist es nicht atomar. Zum anderen ist es langsamer, insbesondere bei großen Dateien. Ich bin neu bei Ansible, aber das scheint mir wirklich komisch zu sein.
mlissner
19
@alex Was ich sage ist, kann nicht der richtige Weg sein, dies zu tun. Ich gehe gegen 50 Gegenstimmen gegen den Wind, aber das ist verrückt. Ein weiteres Problem: Berechtigungen und andere Attribute werden nicht beibehalten. Eine andere: Was ist, wenn die Datei während des Kopierens geändert wird ?
mlissner
2
@ Hamish Downer und mlissner. Ich habe nicht gesagt, dass es die beste Lösung für alle Ihre Bedürfnisse ist. Außerdem habe ich geschrieben, dass Sie das Kopiermodul nicht verwenden sollten, wenn Sie viele Dateien kopieren möchten. Lesen Sie die Frage "Ich möchte die Befehls- / Shell-Aufgaben nicht verwenden".
Alex
7
@Alex Dies ist die zweithöchste Antwort auf eine Frage zum idempotenten Verschieben von Dateien. Die Frage ist nicht über das Kopieren. Es gibt viele Probleme beim Kopieren statt beim Verschieben, daher ist diese Antwort falsch. Also wird es abgelehnt. Etikette auf SO ist es, Abstimmungen zu erklären. Wie an anderer Stelle erwähnt, ist die beste Option bishercommand: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Alec Wenzowski
106

Ich habe die Option "Erstellen" im Befehlsmodul als nützlich empfunden. Wie wäre es damit:

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

Früher habe ich einen 2-Aufgaben-Ansatz mit stat durchgeführt, wie Bruce P vorschlägt. Jetzt mache ich das als eine Aufgabe mit erstellt. Ich denke, das ist viel klarer.

Tom Ekberg
quelle
60
Oder noch besser: command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Fonant
8

Eine andere Option, die für mich gut funktioniert hat, ist die Verwendung des Synchronisierungsmoduls . Entfernen Sie dann das ursprüngliche Verzeichnis mit dem Dateimodul.

Hier ist ein Beispiel aus den Dokumenten:

- synchronize:
    src: /first/absolute/path
    dest: /second/absolute/path
    archive: yes
  delegate_to: "{{ inventory_hostname }}"
Andrew Becker
quelle
Dies funktioniert nicht in jedem Fall lokal, da destüber SSH zugegriffen wird, auch wenn sich das Verzeichnis auf demselben Computer befindet.
Karl Richter
5

Eine andere Möglichkeit, dies zu erreichen, ist die Verwendung filemit state: hard.

Dies ist ein Beispiel, an dem ich arbeiten musste:

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

Nur unter localhost (OSX) getestet, sollte aber auch unter Linux funktionieren. Ich kann nicht für Windows sagen.

Beachten Sie, dass absolute Pfade benötigt werden. Sonst würde ich den Link nicht erstellen können. Außerdem können Sie keine Dateisysteme überqueren, sodass die Arbeit mit bereitgestellten Medien möglicherweise fehlschlägt.

Der Hardlink ist dem Verschieben sehr ähnlich, wenn Sie die Quelldatei anschließend entfernen:

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

Ein weiterer Vorteil ist, dass Änderungen beibehalten werden, wenn Sie sich mitten in einem Spiel befinden. Wenn also jemand die Quelle ändert, wird jede Änderung in der Zieldatei wiedergegeben.

Sie können die Anzahl der Links zu einer Datei über überprüfen ls -l. Die Anzahl der Hardlinks wird neben dem Modus angezeigt (z. B. rwxr-xr-x 2, wenn eine Datei 2 Links enthält).

martinczerwi
quelle
2
Leider funktioniert dies nicht für ein Verzeichnis, da für Verzeichnisse keine festen Links zulässig sind (((
Drew
1
Diese Antwort setzt eine Annahme über das Zielsystem voraus, insbesondere, dass sich sowohl src als auch dest auf derselben Partition befinden. Dies ist möglicherweise nicht der Fall und daher sollte diese Antwort nicht verwendet werden.
Mikky
4

Bruce versuchte nicht, das Ziel anzugeben, um zu überprüfen, ob die Datei verschoben werden sollte, wenn sie bereits vorhanden war. Er stellte sicher, dass die zu verschiebende Datei tatsächlich vorhanden war, bevor er den MV versuchte.

Wenn Sie wie Tom daran interessiert sind, sich nur zu bewegen, wenn die Datei noch nicht vorhanden ist, sollten wir Bruce's Check trotzdem in den Mix integrieren:

- 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
gkedge
quelle
3

So habe ich es für mich zum Laufen gebracht:

  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

Im obigen Playbook wird überprüft, ob die Datei abc.xts vorhanden ist, bevor die Datei in den Ordner tmp verschoben wird.

Eduprado
quelle
3
Keine Notwendigkeit zu verwenden when: stat_result.stat.exists == True. Nur zu benutzen when: stat_result.stat.existsist gut genug.
Kuttumiah
Normalerweise benutze ich das, == Trueweil ich immer etwas mache, wenn die Datei nicht gefunden wird oder == False.
Eduprado
Laut offizieller Dokumentationsseite der statModuleigenschaft wird exists ein booleanWert zurückgegeben. Wenn Sie also nur setzen when: stat_result.stat.exists, erfüllt dies die Bedingung, wenn die Datei vorhanden ist, die ebenfalls identisch ist, when: stat_result.stat.exists == Truejedoch mehr Texte und eine unnötige bedingte Prüfung enthält.
Kuttumiah
0

Dies mag wie ein Overkill erscheinen, aber wenn Sie die Verwendung des Befehlsmoduls vermeiden möchten (was ich tue, weil die Verwendung des Befehls nicht idempotent ist), können Sie eine Kombination aus Kopieren und Nichtarchivieren verwenden.

  1. Verwenden Sie tar, um die benötigten Dateien zu archivieren. Wenn Sie vorausdenken, ist dies tatsächlich sinnvoll. Möglicherweise möchten Sie eine Reihe von Dateien in einem bestimmten Verzeichnis. Erstellen Sie dieses Verzeichnis mit allen Dateien und archivieren Sie sie in einem Teer.
  2. Verwenden Sie das nicht archivierte Modul. Wenn Sie dies tun, können Sie zusammen mit dem Schlüsselwort destination: und remote_src: zunächst alle Ihre Dateien in einen temporären Ordner kopieren und sie dann genau dort entpacken, wo Sie möchten.
Mark Chassy
quelle
Es gibt keine Idempotenz bei der Archivierung mit Teer
visit1985
0

Sie können es tun, indem Sie -

Verwenden des Ad-hoc-Befehls

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

Oder Sie, wenn Sie es mit Playbook tun möchten

- name: Move File foo to destination bar
  command: mv /path/to/foo /path/to/bar
Dev pokhariya
quelle
0

Ich weiß , es ist ein JAHR altes Thema ist, aber ich war frustriert und habe mir eine Rolle aufgebaut, um genau dies für eine beliebige Liste von Dateien zu tun. Verlängern Sie nach Belieben:

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

Beachten Sie, dass eine harte Verknüpfung dem Kopieren hier vorzuziehen ist, da dadurch die Eigentumsrechte und Berechtigungen von Natur aus erhalten bleiben (zusätzlich dazu, dass nicht mehr Speicherplatz für eine zweite Kopie der Datei benötigt wird).

Orlach
quelle
0

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

Verwenden Sie zum Umbenennen stattdessen den Befehl rename oder ren

Vitaly
quelle