Как создать пустой файл с помощью Ansible?


115

Как проще всего создать пустой файл с помощью Ansible? Я знаю, что могу сохранить пустой файл в filesкаталог, а затем скопировать его на удаленный хост, но я считаю это несколько неудовлетворительным.

Другой способ - прикоснуться к файлу на удаленном хосте:

- name: create fake 'nologin' shell
  file: path=/etc/nologin state=touch owner=root group=sys mode=0555

Но затем к файлу каждый раз прикасаются, что отображается в журнале как желтая линия, что тоже неудовлетворительно ...

Есть ли лучшее решение этой простой проблемы?

Ответы:


189

В документации файлового модуля говорится

Если state=fileфайл НЕ будет создан, если он не существует, см. Модуль копирования или шаблона, если вы хотите такого поведения.

Поэтому мы используем модуль копирования, используя force=noдля создания нового пустого файла только тогда, когда файл еще не существует (если файл существует, его содержимое сохраняется).

- name: ensure file exists
  copy:
    content: ""
    dest: /etc/nologin
    force: no
    group: sys
    owner: root
    mode: 0555

Это декларативное и элегантное решение.


15
@ ÁkosVandra: На самом деле это не так. См: force: no.
— palacsint 02

Спасибо - это гораздо более приятное решение, чем файл / касание или принятый ответ stat / file, и его легко сделать с помощью «with_items»
— Realist

Отличный ответ, было любопытно, как создать два пустых файла, используя ту же конструкцию, которую вы предоставили?
— Тасдик Рахман

Есть ли способ создать родительский каталог, если он не существует, или мне нужно сделать это отдельно?
— falsePockets

Вам необходимо убедиться, что родительский каталог существует и доступен для записи. См. Stackoverflow.com/questions/22844905/…
— Рене Пейл,

37

Что-то вроде этого ( statсначала используя модуль для сбора данных о нем, а затем фильтруя его с помощью условного выражения) должно работать:

- stat: path=/etc/nologin
  register: p

- name: create fake 'nologin' shell
  file: path=/etc/nologin state=touch owner=root group=sys mode=0555
  when: p.stat.exists is defined and not p.stat.exists

В качестве альтернативы вы можете использовать эту changed_whenфункциональность.


20
может быть , это Шоуда быть: «когда: не p.stat.exists»
— Пиро

28

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

- name: Create file
  command: touch /path/to/file
  args:
    creates: /path/to/file

Аргумент «создает» гарантирует, что это действие не будет выполнено, если файл существует.


5
Вам следует по возможности избегать команды, поскольку она не идемпотентна. ryaneschinger.com/blog/…
— redshark1802

4
@ redshark1802 Согласен. Хотя в этом случае задача идемпотентна, так как она не будет выполнена, если «/ путь / к / файлу» уже существует. Я думаю, что решение Рене Пейла больше похоже на Ansible из трех основных ответов, и определенно то, что вы должны использовать, если вам нужно установить право собственности, режим и т. Д.
— Leynos

15

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

- stat: path=/etc/nologin
  register: p

- name: create fake 'nologin' shell
  file: path=/etc/nologin 
        owner=root
        group=sys
        mode=0555
        state={{ "file" if  p.stat.exists else "touch"}}

3
Этот ответ великолепен из-за гибкости, которую он дает вам при определении атрибутов файла, если он не существует.
— Dejay Clayton

10

file: path=/etc/nologin state=touch

Полный эквивалент касания (новое в 1.4+) - используйте stat, если вы не хотите изменять временную метку файла.


3
Это не идемпотент, дата файла будет изменяться при каждом запуске доступного playbook.
— Jérôme B

3
@ Jérôme B Новое в Ansible 2.7: вы можете сделать его идемпотентным с помощью file: path=/etc/nologin state=touch modification_time=preserve access_time=preserve.
— GregV

8

файловый модуль предоставляет возможность прикоснуться к файлу без изменения его времени.

- name: Touch again the same file, but dont change times this makes the task idempotent
  file:
    path: /etc/foo.conf
    state: touch
    mode: u+rw,g-wx,o-rwx
    modification_time: preserve
    access_time: preserve

Ссылка: https://docs.ansible.com/ansible/latest/modules/file_module.html


Это правильный ответ для ansible 2.7+, однако в нем отсутствует эта важная информация.
— Хонза

3

Оказывается, у меня недостаточно репутации, чтобы поместить это в качестве комментария, которое было бы более подходящим местом для этого:

Число рейнольдса Ответ AllBlackt, если вы предпочитаете многострочный формат Ansible, вам нужно настроить цитирование state(я потратил несколько минут на разработку этого, так что, надеюсь, это ускорит кого-то другого),

- stat:
    path: "/etc/nologin"
  register: p

- name: create fake 'nologin' shell
  file:
    path: "/etc/nologin"
    owner: root
    group: sys
    mode: 0555
    state: '{{ "file" if  p.stat.exists else "touch" }}'

0

Чтобы создать файл на удаленном компьютере с помощью специальной команды

ansible client -m file -a"dest=/tmp/file state=touch"

Пожалуйста, поправьте меня, если я ошибаюсь


0

Изменяется, если файл не существует. Создать пустой файл.

- name: create fake 'nologin' shell
  file:
    path: /etc/nologin
    state: touch
  register: p
  changed_when: p.diff.before.state == "absent"

0

Комбинация двух ответов с изюминкой. Код будет определен как измененный при создании файла или обновлении разрешений.

- name: Touch again the same file, but dont change times this makes the task idempotent
  file:
    path: /etc/foo.conf
    state: touch
    mode: 0644
    modification_time: preserve
    access_time: preserve
  changed_when: >
    p.diff.before.state == "absent" or
    p.diff.before.mode|default("0644") != "0644"

и версия, которая также исправляет владельца и группу и определяет их как измененные, когда это исправляет:

- name: Touch again the same file, but dont change times this makes the task idempotent
  file:
    path: /etc/foo.conf
    state: touch
    state: touch
    mode: 0644
    owner: root
    group: root
    modification_time: preserve
    access_time: preserve
  register: p
  changed_when: >
    p.diff.before.state == "absent" or
    p.diff.before.mode|default("0644") != "0644" or
    p.diff.before.owner|default(0) != 0 or
    p.diff.before.group|default(0) != 0

только ansible 2.7+ - об этом следует упомянуть.
— Хонза
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.