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

Chr*_*ndt 184 ansible

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

Ale*_*lex 205

从版本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
Run Code Online (Sandbox Code Playgroud)

如果要移动文件,则需要使用文件模块删除旧文件

- name: Remove old files foo
  file: path=/path/to/foo state=absent
Run Code Online (Sandbox Code Playgroud)

  • 小话:"目前remote_src不支持递归复制." 取自ansible模块doc.因此,如果要递归复制,还需要shell /命令模块. (28认同)
  • 我不明白.复制然后删除与移动不同.首先,它不是原子的.另一方面,它更慢,特别是对于大文件.我是Ansible的新手,但这对我来说似乎很奇怪. (19认同)
  • @alex我所说的不是正确的方法.我要迎战50投票,但这很疯狂.另一个问题:不维护权限和其他属性.另一个:如果文件[在复制过程中被更改](http://unix.stackexchange.com/a/6928)怎么办? (16认同)
  • 投票:*复制不动* (9认同)
  • @Alex这是关于幂等移动文件的问题的第二高投票答案.问题不在于复制.复制有许多问题而不是移动,因此这个答案是不正确的.所以它得到了一个downvote.关于SO的礼仪是解释downvotes.如别处所述,到目前为止最好的选择是`命令:mv/path/to/foo/path/to/bar creates =/path/to/bar removed =/path/to/foo` (6认同)
  • @Hamish Downer和mlissner.我没有说这是满足您所有需求的最佳解决方案.我还写道,如果你想复制许多文件,你不应该使用复制模块.阅读"我不想使用命令/ shell任务"的问题. (2认同)
  • 这个答案对于这个问题来说是错误的,而且这是一种可怕的鼓励做法。我为社区感到难过,@Alex 不接受这里的推回,只是编辑/删除他的答案。如果不好的赞成票真的很重要,那么它比一个好的答案更能体现自豪感。 (2认同)

Bru*_*e P 188

文件模块不会复制远程系统上的文件.src参数仅在创建文件的符号链接时由文件模块使用.

如果要在远程系统上完全移动/重命名文件,那么最好的办法是使用命令模块调用相应的命令:

- name: Move foo to bar
  command: mv /path/to/foo /path/to/bar
Run Code Online (Sandbox Code Playgroud)

如果你想获得花哨,那么你可以先使用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
Run Code Online (Sandbox Code Playgroud)

  • 关于在你跳跃之前看:是否有任何理由不对`command`模块使用`removed`选项(文件[here](http://docs.ansible.com/command_module.html))?似乎该选项将首先进行Ansible检查. (10认同)
  • 不使用命令模块,关于您唯一的其他选择是编写自己的自定义模块. (3认同)
  • 如果使用`removes:/ path / to / foo`和`creates:/ path / to / bar`,则不必手动检查文件是否存在。@Fonant已经提到此作为对另一个答案的评论,但是由于这是公认的答案,因此我想再次指出。 (3认同)
  • 标记为正确答案,因为这是复制远程文件的当前方式. (2认同)
  • Ansible 跟踪更改以通知处理程序,这使得此解决方案不是最理想的。 (2认同)
  • downvote不使用`removed:/ path/to/foo`和`creates:/ path/to/bar` (2认同)

小智 100

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

- name: Move foo to bar
  command: creates="path/to/bar" mv /path/to/foo /path/to/bar
Run Code Online (Sandbox Code Playgroud)

我曾经像Bruce P建议的那样使用stat进行2任务处理.现在,我将此作为创建的一项任务.我认为这更加清晰.

  • 或者,甚至更好:`命令:mv/path/to/foo/path/to/bar creates =/path/to/bar removed =/path/to/foo` (56认同)

小智 10

我知道这是一个多年前的话题,但我感到沮丧,并为自己建立了一个角色来对任意文件列表执行此操作。根据您认为合适的情况进行扩展:

主.yml

- name: created destination directory
  file:
    path: /path/to/directory
    state: directory
    mode: '0750'
- include_tasks: move.yml
  loop:
    - file1
    - file2
    - file3
Run Code Online (Sandbox Code Playgroud)

移动.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
Run Code Online (Sandbox Code Playgroud)

请注意,硬链接比此处的复制更可取,因为它本质上保留了所有权和权限(除了不会为文件的第二个副本消耗更多磁盘空间之外)。

  • 这不适用于跨分区 (3认同)

小智 8

另一个对我有用的选项是使用同步模块.然后使用文件模块删除原始目录.

以下是文档中的示例:

- synchronize:
    src: /first/absolute/path
    dest: /second/absolute/path
    archive: yes
  delegate_to: "{{ inventory_hostname }}"
Run Code Online (Sandbox Code Playgroud)


小智 5

这是我让它为我工作的方式:

  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
Run Code Online (Sandbox Code Playgroud)

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

  • 无需使用`when: stat_result.stat.exists == True`。只使用 `when: stat_result.stat.exists` 就足够了。 (3认同)

mar*_*rwi 5

实现这一目标的另一种方法是使用filestate: hard

这是我必须工作的一个示例:

- name: Link source file to another destination
  file:
    src: /path/to/source/file
    path: /target/path/of/file
    state: hard
Run Code Online (Sandbox Code Playgroud)

虽然仅在localhost(OSX)上进行了测试,但也应在Linux上工作。我不能告诉Windows。

请注意,需要绝对路径。否则,不会让我创建链接。另外,您无法跨文件系统,因此使用任何已挂载的媒体可能会失败。

如果之后删除源文件,则硬链接与移动非常相似:

- name: Remove old file
  file:
    path: /path/to/source/file
    state: absent
Run Code Online (Sandbox Code Playgroud)

另一个好处是,当您处于播放过程中时,更改会保持不变。因此,如果有人更改了源,则任何更改都会反映在目标文件中。

您可以通过验证到文件的链接数ls -l。硬链接数显示在该模式旁边(例如,当文件有2个链接时,rwxr-xr-x 2)。

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

Ear*_*uby 5

- name: Move the src file to dest
  command: mv /path/to/src /path/to/dest
  args:
    removes: /path/to/src
    creates: /path/to/dest
Run Code Online (Sandbox Code Playgroud)

mv仅在/path/to/src存在和/path/to/dest不存在时运行命令,因此它在每个主机上运行一次,移动文件,然后不再运行。

当我需要在数百台主机上移动文件或目录时,我会使用这种方法,其中许多主机可能会在任何给定时间关闭。留在剧本中是幂等且安全的。