Как переместить / переименовать файл, используя задачу 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
Без использования командного модуля единственным вашим выбором будет написать собственный модуль.
Брюс П
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 поддерживает рекурсивное копирование.
Небольшое замечание: «В настоящее время 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. Я думаю, что это намного понятнее.
Или еще лучше: command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Fonant
8
Еще один вариант, который хорошо работает для меня, - это использование модуля синхронизации . Затем удалите исходный каталог с помощью файлового модуля.
Это не работает локально в каждом случае, потому что 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 ссылки).
К сожалению, это не будет работать для каталога, так как жесткие ссылки не разрешены для каталогов (((
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
Не нужно использовать when: stat_result.stat.exists == True. Просто использовать when: stat_result.stat.existsдостаточно хорошо.
kuttumiah
Я обычно использую, == Trueпотому что я всегда что-то делаю, когда файл не найден или == False.
19
Согласно официальной странице документацииstatexists свойства модуля возвращают booleanзначение. Таким образом, если вы только поставите, when: stat_result.stat.existsэто будет удовлетворять условию, если файл присутствует, который также идентичен, when: stat_result.stat.exists == Trueно с большим количеством текстов и ненужной условной проверкой.
kuttumiah
0
Это может показаться излишним, но если вы хотите избежать использования командного модуля (что я и делаю, потому что использование команды не идемпотентно), вы можете использовать комбинацию копирования и разархивирования.
Используйте tar для архивации файлов, которые вам понадобятся. Если вы думаете заранее, это действительно имеет смысл. Вы можете хотеть ряд файлов в данном каталоге. Создайте этот каталог со всеми файлами и заархивируйте их в tar.
Используйте модуль разархивирования. Когда вы сделаете это, вместе с ключом destination: и remote_src: вы можете скопировать все ваши файлы во временную папку, а затем распаковать их именно там, где вы хотите.
Я знаю, что это старая тема ЛЕТ , но я разочаровался и создал для себя роль, которая сделает именно это для произвольного списка файлов. Расширьте, как считаете нужным:
- 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
Обратите внимание, что жесткое связывание здесь предпочтительнее, чем копирование, поскольку оно по своей природе сохраняет владение и разрешения (в дополнение к тому, что не занимает больше места на диске для второй копии файла).
Ответы:
Файловый модуль не копирует файлы в удаленной системе. Параметр src используется файловым модулем только при создании символической ссылки на файл.
Если вы хотите переместить / переименовать файл полностью в удаленной системе, тогда вам лучше всего использовать командный модуль, чтобы просто вызвать соответствующую команду:
Если вы хотите получить фантазию, вы можете сначала использовать модуль stat, чтобы убедиться, что foo действительно существует:
источник
removes
опцию дляcommand
модуля (задокументировано здесь )? Похоже, что эта опция сначала сделает проверку Ansible.removes: /path/to/foo
иcreates: /path/to/bar
. @Fonant уже упомянул это как комментарий к другому ответу, но так как он принят, я хочу еще раз указать на это.Начиная с версии 2.0 , в модуле копирования вы можете использовать
remote_src
параметр.Если
True
это пойдет на удаленный / целевой компьютер для src.Если вы хотите переместить файл, вам нужно удалить старый файл с файловым модулем
Начиная с версии 2.8 модуль копирования
remote_src
поддерживает рекурсивное копирование.источник
command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Я нашел параметр create в командном модуле полезным. Как насчет этого:
Я использовал подход с двумя задачами, используя stat, как предлагает Брюс П. Теперь я делаю это как одно задание с create. Я думаю, что это намного понятнее.
источник
command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Еще один вариант, который хорошо работает для меня, - это использование модуля синхронизации . Затем удалите исходный каталог с помощью файлового модуля.
Вот пример из документации:
источник
dest
доступ через SSH, даже если каталог находится на той же машине.Еще один способ добиться этого - использовать
file
сstate: hard
.Это пример, который я получил на работу:
Только проверено на localhost (OSX), но должно работать и на Linux. Я не могу сказать для Windows.
Обратите внимание, что необходимы абсолютные пути. Иначе это не позволило бы мне создать ссылку. Также вы не можете пересекать файловые системы, поэтому работа с любым подключенным носителем может не получиться.
Жесткая ссылка очень похожа на перемещение, если впоследствии удалить исходный файл:
Еще одним преимуществом является то, что изменения сохраняются, когда вы находитесь в середине игры. Поэтому, если кто-то изменяет источник, любое изменение отражается в целевом файле.
Вы можете проверить количество ссылок на файл через
ls -l
. Количество жестких ссылок отображается рядом с режимом (например, rwxr-xr-x 2, когда файл имеет 2 ссылки).источник
Брюс не пытался определить пункт назначения, чтобы проверить, перемещать ли файл, если он уже был там; он следил за тем, чтобы файл, который нужно переместить, действительно существовал, прежде чем пытаться запустить mv.
Если ваш интерес, как и у Тома, состоит в том, чтобы перемещаться, только если файл еще не существует, я думаю, что мы все равно должны интегрировать чек Брюса в микс:
источник
Вот так у меня это получилось:
вышеприведенный playbook, проверит, существует ли файл abc.xts, перед тем как переместить файл в папку tmp.
источник
when: stat_result.stat.exists == True
. Просто использоватьwhen: stat_result.stat.exists
достаточно хорошо.== True
потому что я всегда что-то делаю, когда файл не найден или== False
.stat
exists
свойства модуля возвращаютboolean
значение. Таким образом, если вы только поставите,when: stat_result.stat.exists
это будет удовлетворять условию, если файл присутствует, который также идентичен,when: stat_result.stat.exists == True
но с большим количеством текстов и ненужной условной проверкой.Это может показаться излишним, но если вы хотите избежать использования командного модуля (что я и делаю, потому что использование команды не идемпотентно), вы можете использовать комбинацию копирования и разархивирования.
источник
Вы можете сделать это путем -
Использование специальной команды
Или вы, если вы хотите сделать это с помощью playbook
источник
Я знаю, что это старая тема ЛЕТ , но я разочаровался и создал для себя роль, которая сделает именно это для произвольного списка файлов. Расширьте, как считаете нужным:
main.yml
move.yml
Обратите внимание, что жесткое связывание здесь предпочтительнее, чем копирование, поскольку оно по своей природе сохраняет владение и разрешения (в дополнение к тому, что не занимает больше места на диске для второй копии файла).
источник
В Windows:
- name: Move old folder to backup win_command: "cmd.exe /c move /Y {{ sourcePath }} {{ destinationFolderPath }}"
Для переименования используйте команду переименования или команды ren
источник