Как создать пустой файл с помощью 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функциональность.

ceejayoz
источник
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"}}
AllBlackt
источник
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+ - об этом следует упомянуть.
Хонза