Как переместить / переименовать файл, используя задачу 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
Ansible отслеживает изменения, чтобы уведомить обработчик, что делает это решение неоптимальным.
Boh
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 поддерживает рекурсивное копирование.

Alex
источник
29
Небольшое замечание: «В настоящее время remote_src не поддерживает рекурсивное копирование». взято из ответного модуля док. Поэтому, если вы хотите копировать рекурсивно, вам все равно нужен командный модуль shell /.
Клаас
23
Я не понимаю Копирование и удаление - это не то же самое, что перемещение. С одной стороны, это не атомарно. С другой стороны, это медленнее, особенно для больших файлов. Я новичок в Ansible, но мне это кажется странным.
mlissner
19
@alex, что я говорю, не может быть правильным способом сделать это. Я иду против ветра против чего-то против 50, но это безумие. Другая проблема: разрешения и другие атрибуты не поддерживаются. Другое: Что если файл будет изменен во время копирования ?
mlissner
2
@ Хэмиш Даунер и Млисснер. Я не говорил, что это лучшее решение для всех ваших нужд. Также я написал, что если вы хотите скопировать много файлов, вы не должны использовать модуль копирования. Прочитайте вопрос «Я не хочу использовать задачи команды / оболочки».
Алекс,
7
@ Алекс, это второй по популярности ответ на вопрос о идемпотентно движущихся файлах. Вопрос не в копировании. Есть много проблем с копированием вместо перемещения, поэтому этот ответ неверен. Так что это получает отрицательный голос. Этикет на ТА должен объяснять отрицательные стороны. Как отмечалось в другом месте, лучший вариант до сих пор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

Я использовал подход с двумя задачами, используя stat, как предлагает Брюс П. Теперь я делаю это как одно задание с 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 ссылки).

martinczerwi
источник
2
К сожалению, это не будет работать для каталога, так как жесткие ссылки не разрешены для каталогов (((
Drew
1
Этот ответ делает предположение о целевой системе, а именно, что src и dest находятся в одном разделе. Это не может быть правдой, и поэтому этот ответ не должен использоваться.
Микки
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
gkedge
источник
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

вышеприведенный playbook, проверит, существует ли файл abc.xts, перед тем как переместить файл в папку tmp.

eduprado
источник
3
Не нужно использовать when: stat_result.stat.exists == True. Просто использовать when: stat_result.stat.existsдостаточно хорошо.
kuttumiah
Я обычно использую, == Trueпотому что я всегда что-то делаю, когда файл не найден или == False.
19
Согласно официальной странице документацииstat exists свойства модуля возвращают booleanзначение. Таким образом, если вы только поставите, when: stat_result.stat.existsэто будет удовлетворять условию, если файл присутствует, который также идентичен, when: stat_result.stat.exists == Trueно с большим количеством текстов и ненужной условной проверкой.
kuttumiah
0

Это может показаться излишним, но если вы хотите избежать использования командного модуля (что я и делаю, потому что использование команды не идемпотентно), вы можете использовать комбинацию копирования и разархивирования.

  1. Используйте tar для архивации файлов, которые вам понадобятся. Если вы думаете заранее, это действительно имеет смысл. Вы можете хотеть ряд файлов в данном каталоге. Создайте этот каталог со всеми файлами и заархивируйте их в tar.
  2. Используйте модуль разархивирования. Когда вы сделаете это, вместе с ключом destination: и remote_src: вы можете скопировать все ваши файлы во временную папку, а затем распаковать их именно там, где вы хотите.
Марк Часси
источник
Идемпотентность в архивировании с помощью tar отсутствует
visit1985
0

Вы можете сделать это путем -

Использование специальной команды

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

Или вы, если вы хотите сделать это с помощью playbook

- name: Move File foo to destination bar
  command: mv /path/to/foo /path/to/bar
Dev похария
источник
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

Обратите внимание, что жесткое связывание здесь предпочтительнее, чем копирование, поскольку оно по своей природе сохраняет владение и разрешения (в дополнение к тому, что не занимает больше места на диске для второй копии файла).

Orlach
источник
0

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

Для переименования используйте команду переименования или команды ren

Виталий
источник