Як перемістити / перейменувати файл за допомогою завдання Ansible у віддаленій системі


202

Як можна переміщувати / перейменувати файл / каталог за допомогою модуля Ansible у віддаленій системі? Я не хочу використовувати завдання команд / оболонок і не хочу копіювати файл з локальної системи у віддалену систему.


Чому ви не хочете використовувати команду / оболонку?
Нік Урбан

4
Просто хотів дізнатися, чи є спосіб без використання згаданих завдань. Схоже, іншого шляху немає на даний момент.
Крістіан Берендт

1
Чому ви хочете спеціально перемістити його, а не копіювати? Це схоже на разову дію, а не на безсумнівний крок, що забезпечує стан системи.
Нік Урбан

2
У мене в пакеті RPM є зразок конфігураційного файла, і я хочу перемістити цей зразок конфігураційного файлу.
Крістіан Берендт

1
На даний момент я використовую симпосилання для посилання на файл. Використання get_url не є для мене варіантом, оскільки система не може зайти в Інтернет.
Крістіан Берендт

Відповіді:


201

Файловий модуль не копіює файли у віддалену систему. Параметр src використовується модулем файлів лише при створенні символьного посилання на файл.

Якщо ви хочете перемістити / перейменувати файл повністю у віддаленій системі, то найкраще зробити команду, щоб просто викликати відповідну команду:

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

Якщо ви хочете пофантазувати, то спочатку ви можете скористатися модулем stat, щоб перевірити, чи дійсно foo існує:

- 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
Без використання командного модуля вашим єдиним іншим вибором було б написати власний модуль.
Брюс П

2
Позначена як правильна відповідь, оскільки це поточний спосіб копіювання віддалених файлів.
Крістіан Берендт

11
Щодо перегляду, перш ніж стрибати: чи є причина, щоб не використовувати removesпараметр для commandмодуля ( тут задокументовано )? Здається, що цей варіант спочатку зробить перевірку Ansible.
Джим Вітчей

2
Відповідні треки змінюються, щоб повідомити обробника, що робить це рішення неоптимальним.
бох

3
Вам не потрібно вручну перевіряти наявність файлу, якщо ви використовуєте removes: /path/to/fooта creates: /path/to/bar. @Fonant вже згадував це як коментар до іншої відповіді, але оскільки це прийнято, я хочу його ще раз зазначити.
Майкл Троянек

218

З версії 2.0 в модулі копіювання можна використовувати remote_srcпараметр.

Якщо Trueвін перейде до віддаленої / цільової машини для src.

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

Якщо ви хочете перемістити файл, вам потрібно видалити старий файл із файлового модуля

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

З версії 2.8 модуль копіювання remote_src підтримує рекурсивне копіювання.


29
Невелике зауваження: "В даний час remote_src не підтримує рекурсивне копіювання." взяті з довідкового модуля док. Отже, якщо ви хочете скопіювати рекурсивно, вам все одно потрібен модуль оболонки / команди.
klaas

23
Я не розумію. Копіювання та видалення не те саме, що переміщення. Для одного це не атомно. Для іншого це повільніше, особливо для великих файлів. Я новачок у Ansible, але це здається мені справді дивним.
mlissner

19
@ Алекс, те, що я кажу, не може бути правильним способом зробити це. Я йду по вітру проти 50-ти щось, але це божевільно. Інша проблема: дозволи та інші атрибути не підтримуються. Ще: Що робити, якщо файл було змінено під час копіювання ?
mlissner

2
@Hamish Downer і mlissner. Я не сказав, що це найкраще рішення для всіх ваших потреб. Також я написав, що якщо ви хочете скопіювати багато файлів, ви не повинні використовувати модуль копіювання. Прочитайте питання "Я не хочу використовувати завдання команди / оболонки".
Олексій

7
@Alex - це другий найвищий відповідь на запитання про безвідмовне переміщення файлів. Питання не в копіюванні. Існує багато проблем з копіюванням, а не переміщенням, тому ця відповідь невірна. Так він отримує протизаконний голос. Етикет на SO - це пояснення низових запитів. Як було зазначено в іншому місці, найкращим варіантом поки що єcommand: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Алек Вензовський

106

Я вважаю корисною опцію create у командному модулі. Як щодо цього:

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

Раніше я робив підхід із двома завданнями, використовуючи статистику, як пропонує Брюс П. Тепер я роблю це як одне завдання з create. Я думаю, це набагато зрозуміліше.


60
Або ще краще: command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Fonant

8

Інший варіант, який добре працював для мене, - це використання модуля синхронізації . Потім видаліть оригінальний каталог за допомогою модуля файлів.

Ось приклад із документів:

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

Це не працює на локальному рівні в кожному випадку, оскільки destдоступ до нього здійснюється через SSH, навіть якщо каталог знаходиться на одній машині.
Карл Ріхтер

5

Ще одним способом досягти цього є використання за fileдопомогою state: hard.

Це приклад, над яким я працював:

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

Хоча тестується лише на localhost (OSX), але він також повинен працювати на Linux. Я не можу сказати для Windows.

Зауважте, що потрібні абсолютні шляхи. Інакше це не дозволило б мені створити посилання. Крім того, ви не можете перетинати файлові системи, тому робота з будь-яким встановленим носієм може не вдатися.

Жорстке посилання дуже схоже на переміщення, якщо згодом ви видалите вихідний файл:

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

Ще одна перевага полягає в тому, що зміни зберігаються, коли ви знаходитесь в середині вистави. Отже, якщо хтось змінює джерело, будь-яка зміна відображається у цільовому файлі.

Ви можете перевірити кількість посилань на файл за допомогою ls -l. Кількість жорстких посилань відображається поруч із режимом (наприклад, rwxr-xr-x 2, коли файл має 2 посилання).


2
На жаль, це не працюватиме для каталогу, оскільки жорсткі посилання не дозволені для каталогів (((
Drew

1
Ця відповідь робить припущення про цільову систему, зокрема, що src і dest знаходяться на одному розділі. Це може бути неправдою, тому цю відповідь не слід використовувати.
Mikky

4

Брюс не намагався зафіксувати місце призначення, щоб перевірити, чи слід переміщувати файл, чи він уже є; він намагався перенести файл насправді, перш ніж спробувати mv.

Якщо ваш інтерес, як у Тома, рухається лише в тому випадку, якщо файл уже не існує, я думаю, нам все ж слід інтегрувати перевірку Брюса в суміш:

- 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

Це так, як я працював на мене:

  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

в ігровій книжці вище, перевірте, чи існує файл abc.xts, перш ніж перемістити файл у папку tmp


3
Не потрібно користуватися when: stat_result.stat.exists == True. Просто використання when: stat_result.stat.existsдосить добре.
kuttumiah

Я зазвичай використовую , == Trueтому що я завжди роблю що - то , коли файл не знайдений або == False.
eduprado

Відповідно до сторінки офіційної документації властивості statмодуля exists повертає booleanзначення. Отже, якщо ви поставите лише те, when: stat_result.stat.existsщо буде задовольняти умові, якщо файл присутній, який також ідентичний, when: stat_result.stat.exists == Trueале з більшою кількістю текстів та зайвою умовною перевіркою.
kuttumiah

0

Це може здатися надмірним, але якщо ви хочете уникати використання командного модуля (що я роблю, тому що він за допомогою команди не є ідентичним), ви можете використовувати комбінацію копії та неархівації.

  1. Використовуйте tar для архівації потрібних файлів. Якщо ви заздалегідь думаєте, це насправді має сенс. Можливо, вам потрібна серія файлів у заданому каталозі. Створіть цей каталог із усіма файлами та архівуйте їх у тарі.
  2. Використовуйте модуль анрхівації. Зробивши це разом із ключовим словом призначення: та remote_src:, ви можете розмістити копії всіх своїх файлів у тимчасову папку, а потім розпакуйте їх саме там, де ви хочете.


0

Ви можете це зробити:

Використання спеціальних команд

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

Або Ви, якщо хочете це зробити, скориставшись ігровою книжкою

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

0

Я знаю, що це давня тема РОКІВ , але я розчарувався і створив для себе роль зробити саме це для довільного списку файлів. Розширити, як вважаєте за потрібне:

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

Зауважте, що жорстке посилання бажано скопіювати тут, оскільки воно по суті зберігає право власності та дозволи (крім того, що не витрачається більше місця на диску для другої копії файлу).


0

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

Щоб перейменувати, замість цього скористайтеся командою перейменування або ren

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.