如何在远程系统上使用Ansible任务移动/重命名文件


202

如何在远程系统上使用Ansible模块移动/重命名文件/目录?我不想使用命令/ shell任务,也不想将文件从本地系统复制到远程系统。


您为什么不想使用命令/ shell?
Nick Urban

4
只是想知道是否有一种方法不使用上述任务。看来目前没有其他方法。
Christian Berendt 2014年

1
为什么要专门移动它而不是复制它?这似乎是一次性的操作,而不是确定系统状态类型的幂等步骤。
Nick Urban

2
我在RPM软件包中包含一个示例配置文件,我想移动此示例配置文件。
Christian Berendt 2014年

1
目前,我正在使用符号链接来引用文件。我无法使用get_url,因为系统无法访问互联网。
Christian Berendt 2014年

Answers:


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

3
如果不使用命令模块,则唯一的选择就是编写自己的自定义模块。
Bruce P

2
标记为正确答案,因为这是当前复制远程文件的方法。
Christian Berendt 2014年

11
关于飞跃前的思考:是否有任何理由不对模块使用此removes选项command在此处记录)?似乎该选项将首先进行Ansible检查。
Jim Witschey 2015年

2
Ansible跟踪更改以通知处理程序,这使该解决方案不理想。
boh 2015年

3
如果使用removes: /path/to/foo和,则不必手动检查文件的存在creates: /path/to/bar。@Fonant已经提到此作为对另一答案的评论,但是由于这是已接受的答案,因此我想再次指出。
Michael Trojanek

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支持递归复制。


29
小注释:“当前remote_src不支持递归复制。” 取自ansible模块文档。因此,如果要递归复制,您仍然需要shell / command模块。
klaas

23
我不明白 复制然后删除与移动不同。首先,它不是原子的。另一方面,它的速度较慢,尤其是对于大文件。我是Ansible的新手,但这对我来说真的很奇怪。
mlissner '16

19
@alex我要说的不是正确的方法。我要迎接50项投票,但是这太疯狂了。另一个问题:权限和其他属性无法维护。另一个:如果在复制过程中更改了文件怎么办?
mlissner's

2
@Hamish Downer和mlissner。我并不是说这是满足您所有需求的最佳解决方案。我还写道,如果要复制许多文件,则不应使用复制模块。阅读问题“我不想使用命令/ shell任务”。
亚历克斯(Alex)

7
@Alex这是有关幂等移动文件的问题的第二高投票解答。问题不在于复制。复制而不是移动存在很多问题,因此此答案不正确。因此,它产生了负面影响。SO上的礼节是要解释降票。如其他地方所述,到目前为止最好的选择是command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Alec Wenzowski

106

我发现命令模块中的创建选项很有用。这个怎么样:

- name: Move foo to bar
  command: creates="path/to/bar" mv /path/to/foo /path/to/bar

我曾经像Bruce P建议的那样使用统计量执行2任务方法。现在,我将创建作为一项任务来完成。我认为这要清楚得多。


60
或者,甚至更好: command: mv /path/to/foo /path/to/bar creates=/path/to/bar removes=/path/to/foo
Fonant 2015年

8

对我来说效果很好的另一个选项是使用syncize模块。然后使用文件模块删除原始目录。

这是文档中的示例:

- synchronize:
    src: /first/absolute/path
    dest: /second/absolute/path
    archive: yes
  delegate_to: "{{ inventory_hostname }}"

这在每种情况下都无法在本地工作,因为dest即使目录位于同一台计算机上,也可以通过SSH访问它。
里希

5

实现这一目标的另一种方法是使用filestate: 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。硬链接的数量显示在该模式旁边(例如,当文件具有2个链接时,rwxr-xr-x 2)。


2
不幸的是,这不适用于目录,因为目录不允许硬链接((((
Drew

1
这个答案假设一个关于目标系统的假设,特别是src和dest都在同一个分区上。这可能不是正确的,因此不应使用此答案。
mikky

4

Bruce并没有尝试指定目的地以检查是否已移动文件(如果该文件已经存在)。在尝试执行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

3

这是我为我工作的方式:

  Tasks:
  - name: checking if the file 1 exists
     stat:      
      path: /path/to/foo abc.xts
     register: stat_result

  - name: moving file 1
    command: mv /path/to/foo abc.xts /tmp
    when: stat_result.stat.exists == True

上面的剧本,在将文件移到tmp文件夹之前,将检查文件abc.xts是否存在。


3
无需使用when: stat_result.stat.exists == True。仅使用when: stat_result.stat.exists就足够了。
kuttumiah

我通常使用,== True因为找不到文件或时总是会做某事== False
eduprado '19

根据模块属性的官方文档页面stat exists返回boolean值。因此,如果您只提供when: stat_result.stat.exists满足条件的文件(如果存在),该文件也相同,when: stat_result.stat.exists == True但包含更多文本和不必要的条件检查。
kuttumiah

0

这似乎有点过分,但是如果您想避免使用命令模块(我这样做,因为它使用命令不是幂等的),则可以使用复制和取消归档的组合。

  1. 使用tar存档您需要的文件。如果您提前考虑,这实际上是有道理的。您可能需要给定目录中的一系列文件。使用所有文件创建该目录,并将其存档在tar中。
  2. 使用取消存档模块。在执行此操作时,连同destination:和remote_src:关键字一起,您可以将所有文件复制到一个开始的临时文件夹中,然后将其精确解压缩到所需的位置。

使用tar进行归档没有幂等性
visit1985

0

您可以通过-

使用临时命令

ansible all -m command -a" mv /path/to/foo /path/to/bar"

或者您想使用剧本来做

- name: Move File foo to destination bar
  command: mv /path/to/foo /path/to/bar

0

我知道这是YEARS的旧话题,但是我很沮丧,并且为自己建立了一个角色,可以对任意文件列表执行此操作。视需要扩展:

main.yml

- name: created destination directory
  file:
    path: /path/to/directory
    state: directory
    mode: '0750'
- include_tasks: move.yml
  loop:
    - file1
    - file2
    - file3

move.yml

- 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

请注意,硬链接优于此处的复制,因为硬链接固有地保留了所有权和权限(除了不占用更多磁盘空间用于文件的第二个副本外)。


0

在Windows上: - name: Move old folder to backup win_command: "cmd.exe /c move /Y {{ sourcePath }} {{ destinationFolderPath }}"

要重命名,请改用renameren命令

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.