Jak przenieść / zmienić nazwę pliku za pomocą zadania Ansible w systemie zdalnym

202

Jak można przenieść / zmienić nazwę pliku / katalogu za pomocą modułu Ansible w systemie zdalnym? Nie chcę używać zadań polecenia / powłoki i nie chcę kopiować pliku z systemu lokalnego do systemu zdalnego.

Christian Berendt
źródło
Dlaczego nie chcesz użyć polecenia / powłoki?
Nick Urban
4
Chciałem tylko wiedzieć, czy istnieje sposób bez korzystania ze wspomnianych zadań. Wygląda na to, że w tej chwili nie ma innego wyjścia.
Christian Berendt
1
Dlaczego chcesz go specjalnie przenieść, a nie skopiować? To wydaje się być działaniem jednorazowym, a nie idempotentnym krokiem zapewniającym stan systemu.
Nick Urban
2
Mam przykładowy plik konfiguracyjny zawarty w pakiecie RPM i chcę przenieść ten przykładowy plik konfiguracyjny.
Christian Berendt,
1
W tej chwili używam dowiązania symbolicznego do odwołania do pliku. Korzystanie z get_url nie jest dla mnie opcją, ponieważ system nie może połączyć się z Internetem.
Christian Berendt,

Odpowiedzi:

201

Moduł plików nie kopiuje plików w systemie zdalnym. Parametr src jest używany tylko przez moduł pliku podczas tworzenia dowiązania symbolicznego do pliku.

Jeśli chcesz przenieść / zmienić nazwę pliku w całości na zdalnym systemie, najlepiej jest użyć modułu poleceń, aby po prostu wywołać odpowiednie polecenie:

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

Jeśli chcesz się spodobać, możesz najpierw użyć modułu statystyk, aby sprawdzić, czy foo faktycznie istnieje:

- 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.
źródło
3
Bez korzystania z modułu poleceń jedynym wyborem byłoby napisanie własnego modułu niestandardowego.
Bruce P,
2
Oznaczono jako poprawną odpowiedź, ponieważ jest to obecny sposób kopiowania plików zdalnych.
Christian Berendt
11
Jeśli chodzi o patrzenie przed skokiem: czy jest jakiś powód, aby nie korzystać z removesopcji commandmodułu ( tutaj udokumentowane )? Wygląda na to, że ta opcja sprawi, że najpierw sprawdzimy Ansible.
Jim Witschey
2
Ansible śledzi zmiany, aby powiadomić program obsługi, co powoduje, że to rozwiązanie nie jest optymalne.
boh
3
Nie musisz ręcznie sprawdzać istnienia pliku, jeśli używasz removes: /path/to/fooi creates: /path/to/bar. @Fonant już wspomniał o tym jako komentarz do innej odpowiedzi, ale ponieważ jest to zaakceptowana, chcę to jeszcze raz podkreślić.
Michael Trojanek
218

Od wersji 2.0 w module kopiowania można użyć remote_srcparametru.

Jeśli Trueprzejdzie do zdalnego / docelowego komputera dla src.

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

Jeśli chcesz przenieść plik, musisz usunąć stary plik za pomocą modułu plików

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

Od wersji 2.8 moduł kopiowania remote_src obsługuje kopiowanie rekurencyjne.

Alex
źródło
29
Mała uwaga: „Obecnie remote_src nie obsługuje kopiowania rekurencyjnego”. zaczerpnięte z modułu ansible doc. Więc jeśli chcesz kopiować rekurencyjnie, nadal potrzebujesz powłoki / modułu poleceń.
klaas
23
Nie rozumiem. Kopiowanie, a następnie usuwanie nie jest tym samym, co przenoszenie. Po pierwsze, nie jest atomowy. Po drugie, jest wolniejszy, szczególnie w przypadku dużych plików. Jestem nowy w Ansible, ale wydaje mi się to dziwne.
mlissner,
19
@alex to, co mówię, nie może być dobrym sposobem na zrobienie tego. Idę pod wiatr przeciw 50 głosom pozytywnym, ale to szalone. Kolejny problem: uprawnienia i inne atrybuty nie są utrzymywane. Kolejne: co jeśli plik zostanie zmieniony podczas kopiowania ?
mlissner
2
@Hamish Downer i mlissner. Nie powiedziałem, że to najlepsze rozwiązanie dla wszystkich twoich potrzeb. Napisałem również, że jeśli chcesz skopiować wiele plików, nie powinieneś używać modułu kopiowania. Przeczytaj pytanie „Nie chcę używać poleceń / zadań powłoki”.
Alex
7
@Alex jest to druga najwyżej głosowana odpowiedź na pytanie dotyczące idempotentnego przenoszenia plików. Pytanie nie dotyczy kopiowania. Istnieje wiele problemów z kopiowaniem zamiast przenoszenia, dlatego ta odpowiedź jest niepoprawna. Więc dostaje opinię negatywną. Etykieta dotycząca SO ma na celu wyjaśnienie głosów negatywnych. Jak wspomniano gdzie indziej, najlepszą jak dotąd opcją jestcommand: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Alec Wenzowski
106

Uważam, że opcja create w module poleceń jest przydatna. Co powiesz na to:

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

Kiedyś stosowałem podejście z dwoma zadaniami, używając statystyk, jak sugeruje Bruce P. Teraz robię to jako jedno zadanie z tworzeniem. Myślę, że jest to o wiele wyraźniejsze.

Tom Ekberg
źródło
60
Lub jeszcze lepiej: command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Fonant,
8

Inną opcją, która działała dla mnie dobrze, jest użycie modułu synchronizacji . Następnie usuń oryginalny katalog za pomocą modułu plików.

Oto przykład z dokumentów:

- synchronize:
    src: /first/absolute/path
    dest: /second/absolute/path
    archive: yes
  delegate_to: "{{ inventory_hostname }}"
Andrew Becker
źródło
To nie działa lokalnie w każdym przypadku, ponieważ destjest dostępne przez SSH, nawet jeśli katalog znajduje się na tym samym komputerze.
Karl Richter
5

Innym sposobem na osiągnięcie tego jest użycie filez state: hard.

Oto przykład, który mam do pracy:

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

Testowany tylko na localhost (OSX), ale powinien również działać na Linuksie. Nie mogę powiedzieć dla Windows.

Pamiętaj, że potrzebne są ścieżki bezwzględne. W przeciwnym razie nie pozwoli mi to utworzyć linku. Nie można także krzyżować systemów plików, więc praca z dowolnym zamontowanym nośnikiem może się nie powieść.

Hardlink jest bardzo podobny do przenoszenia, jeśli później usuniesz plik źródłowy:

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

Kolejną korzyścią jest to, że zmiany są utrzymywane, gdy jesteś w trakcie gry. Jeśli więc ktoś zmieni źródło, każda zmiana zostanie odzwierciedlona w pliku docelowym.

Możesz sprawdzić liczbę linków do pliku poprzez ls -l. Liczba twardych dowiązań jest pokazana obok trybu (np. Rwxr-xr-x 2, gdy plik ma 2 dowiązania).

martinczerwi
źródło
2
Niestety, to nie zadziała w przypadku katalogu, ponieważ twarde linki nie są dozwolone w przypadku katalogów (((
Drew
1
Ta odpowiedź zakłada założenie o systemie docelowym, w szczególności, że zarówno src, jak i dest znajdują się na tej samej partycji. To może nie być prawda i dlatego nie należy używać tej odpowiedzi.
mikky
4

Bruce nie próbował statystykować miejsca docelowego, aby sprawdzić, czy przenieść plik, jeśli już tam był; upewniał się, że plik, który ma zostać przeniesiony, faktycznie istniał przed próbą wykonania mv.

Jeśli twoim zainteresowaniem, podobnie jak Toma, jest przeniesienie się tylko wtedy, gdy plik jeszcze nie istnieje, myślę, że nadal powinniśmy zintegrować czek Bruce'a z miksem:

- 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
źródło
3

Oto jak działam dla mnie:

  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

powyższy podręcznik sprawdzi, czy plik abc.xts istnieje przed przeniesieniem pliku do folderu tmp.

eduprado
źródło
3
Nie musisz używać when: stat_result.stat.exists == True. Samo używanie when: stat_result.stat.existsjest wystarczająco dobre.
kuttumiah
Zwykle używam, == Trueponieważ zawsze coś robię, gdy nie można znaleźć pliku lub == False.
eduprado,
Zgodnie z oficjalną dokumentacją stronastat exists właściwości modułu zwraca booleanwartość. Tak więc, jeśli wstawisz when: stat_result.stat.exists, spełni warunek, jeśli plik jest obecny, który jest identyczny, when: stat_result.stat.exists == Trueale zawiera więcej tekstów i niepotrzebne sprawdzenie warunkowe.
kuttumiah
0

Może się to wydawać przesadą, ale jeśli chcesz uniknąć używania modułu poleceń (co robię, ponieważ użycie polecenia nie jest idempotentne), możesz użyć kombinacji kopiowania i archiwizacji.

  1. Użyj tar do zarchiwizowania potrzebnych plików. Jeśli myślisz z wyprzedzeniem, ma to sens. Możesz chcieć serii plików w danym katalogu. Utwórz ten katalog ze wszystkimi plikami i zarchiwizuj je w pliku tar.
  2. Użyj modułu archiwizującego. Gdy to zrobisz, wraz ze słowem kluczowym destination: i remote_src:, możesz skopiować wszystkie pliki do folderu tymczasowego, aby rozpocząć, a następnie rozpakować je dokładnie tam, gdzie chcesz.
Mark Chassy
źródło
Nie ma idempotencji w archiwizacji za pomocą tar
odwiedź 1985
0

Możesz to zrobić przez -

Za pomocą polecenia Ad Hoc

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

Lub Ty, jeśli chcesz to zrobić, korzystając z poradnika

- name: Move File foo to destination bar
  command: mv /path/to/foo /path/to/bar
Dev pokhariya
źródło
0

Wiem, że to stary LATOWY temat, ale denerwowałem się i stworzyłem dla siebie rolę, aby robić to dokładnie na dowolnej liście plików. Rozszerz według własnego uznania:

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

Pamiętaj, że twarde linkowanie jest lepsze niż kopiowanie tutaj, ponieważ z natury zachowuje własność i uprawnienia (oprócz tego, że nie zajmuje więcej miejsca na dysku dla drugiej kopii pliku).

Orlach
źródło
0

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

Aby zmienić nazwę, użyj zamiast tego polecenia rename lub ren

Witalij
źródło