如何使用Ansible创建一个空文件?


115

使用Ansible创建空文件的最简单方法是什么?我知道我可以将一个空文件保存到files目录中,然后将其复制到远程主机,但是我发现这样做有些不满意。

另一种方法是触摸远程主机上的文件:

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

但是随后每次都触摸文件,在日志中显示为黄线,这也不令人满意。

有没有更好的解决方案来解决这个简单的问题?

Answers:


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

谢谢-这是一个比文件/触摸或公认的统计/文件答案更好的解决方案,并且使用“ with_items”可以轻松完成
现实主义者

很好的答案,很好奇,一个人如何使用您提供的相同结构创建两个空文件?
塔斯迪克·拉曼

如果不存在,有没有办法使它创建父目录,还是我需要单独进行创建?
falsePockets

您需要确保父目录存在并且可写。见stackoverflow.com/questions/22844905/...
勒内PIJL

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”
piro 2015年

28

使用命令模块的另一种选择:

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

'creates'参数确保如果文件存在,则不执行此操作。


5
您应该尽可能避免使用命令,因为它不是幂等的。ryaneschinger.com/blog/...
redshark1802

4
@ redshark1802同意。尽管在这种情况下,该任务是幂等的,因为如果“ / path / to / file”已经存在,则将不会执行该任务。我认为RenéPijl的解决方案更像是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
这不是幂等的,文件日期将在ansible剧本的每次执行时进行修改。
杰罗姆乙

3
@JérômeB Ansible 2.7的新功能:您可以使用使其幂等file: path=/etc/nologin state=touch modification_time=preserve access_time=preserve
GregV


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

两个答案的组合,略有不同。创建文件或更新权限后,将检测到代码已更改。

- 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+-应该提及。
Honza
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.