¿Cómo crear un archivo vacío con Ansible?


115

¿Cuál es la forma más fácil de crear un archivo vacío usando Ansible? Sé que puedo guardar un archivo vacío en el filesdirectorio y luego copiarlo en el host remoto, pero eso me parece algo insatisfactorio.

Otra forma es tocar un archivo en el host remoto:

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

Pero luego el archivo se toca cada vez, apareciendo como una línea amarilla en el registro, lo cual tampoco es satisfactorio ...

¿Existe alguna solución mejor para este simple problema?

Respuestas:


189

La documentación del módulo de archivo dice

Si state=file, el archivo NO se creará si no existe, vea el módulo de copia o plantilla si desea ese comportamiento.

Entonces usamos el módulo de copia, usando force=nopara crear un nuevo archivo vacío solo cuando el archivo aún no existe (si el archivo existe, su contenido se conserva).

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

Esta es una solución declarativa y elegante.


15
@ ÁkosVandra: En realidad no es así. Ver: force: no.
palacsint

Gracias, esta es una solución mucho mejor que file / touch o la respuesta stat / file aceptada, y es fácil de hacer con "with_items"
Realista

Gran respuesta, ¿tenía curiosidad sobre cómo se pueden crear dos archivos vacíos utilizando la misma construcción que ha proporcionado?
Tasdik Rahman

¿Hay alguna manera de hacer que esto cree el directorio principal si no existe, o tengo que hacerlo por separado?
falsePockets

Debe asegurarse de que el directorio principal exista y se pueda escribir. Ver stackoverflow.com/questions/22844905/…
René Pijl

37

Algo como esto (usar el statmódulo primero para recopilar datos sobre él y luego filtrar usando un condicional) debería funcionar:

- 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

Alternativamente, podría aprovechar la changed_whenfuncionalidad.


20
tal vez debería ser: "cuando: no existe p.stat."
piro

28

Otra opción, usando el módulo de comando:

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

El argumento 'crea' asegura que esta acción no se realice si el archivo existe.


5
Debe evitar el comando tanto como sea posible, ya que no es idempotente. ryaneschinger.com/blog/…
redshark1802

4
@ redshark1802 De acuerdo. Aunque en este caso la tarea es idempotente, ya que no se ejecutará si "/ ruta / a / archivo" ya existe. Creo que la solución de René Pijl es el más parecido Ansible de los tres mejores respuestas, y sin duda la que se debe utilizar si necesita la propiedad conjunto, modo, etc.
Leynos

15

Sobre la base de la respuesta aceptada, si desea que se verifiquen los permisos del archivo en cada ejecución, y estos se cambian en consecuencia si el archivo existe, o simplemente cree el archivo si no existe, puede usar lo siguiente:

- 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
Esta respuesta es asombrosa debido a la flexibilidad que le brinda para definir los atributos de archivo de un archivo si no existe.
Dejay Clayton

10

file: path=/etc/nologin state=touch

Equivalente completo de touch (nuevo en 1.4+): use stat si no desea cambiar la marca de tiempo del archivo.


3
No es idempotente, la fecha del archivo se modificará en cada ejecución del libro de jugadas ansible.
Jérôme B

3
@ Jérôme B Nuevo en Ansible 2.7: puedes hacerlo idempotente con file: path=/etc/nologin state=touch modification_time=preserve access_time=preserve.
GregV

8

El módulo de archivo proporciona una forma de tocar el archivo sin modificar su tiempo.

- 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

Referencia: https://docs.ansible.com/ansible/latest/modules/file_module.html


Esta es la respuesta correcta para ansible 2.7+, sin embargo, falta información importante.
Honza

3

Resulta que no tengo suficiente reputación para poner esto como comentario, que sería un lugar más apropiado para esto:

Re. La respuesta de AllBlackt, si prefiere el formato multilínea de Ansible, necesita ajustar las cotizaciones state(pasé unos minutos resolviendo esto, así que espero que esto acelere a alguien más),

- 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

Para crear un archivo en la máquina remota con el comando ad-hoc

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

Por favor, corríjame si estoy equivocado


0

Cambiado si el archivo no existe. Crea un archivo vacío.

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

0

Una combinación de dos respuestas, con un giro. El código se detectará como cambiado cuando se cree el archivo o se actualice el permiso.

- 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"

y una versión que también corrige el propietario y el grupo y lo detecta como cambiado cuando corrige estos:

- 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+ solamente - eso debería mencionarse.
Honza
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.