使用 Ansible 复制多个文件

Posted

技术标签:

【中文标题】使用 Ansible 复制多个文件【英文标题】:Copy multiple files with Ansible 【发布时间】:2016-08-10 08:47:43 【问题描述】:

如何在任务中通过 Ansible 将多个文件复制到远程节点?

我试图在我的任务中复制复制模块行来定义文件,但它只复制第一个文件。

【问题讨论】:

【参考方案1】:

您可以为此使用with_fileglob 循环:

- copy:
    src: " item "
    dest: /etc/fooapp/
    owner: root
    mode: 600
  with_fileglob:
    - /playbooks/files/fooapp/*

【讨论】:

如果我将所有文件都放在同一个根目录中以复制到远程机器中,这种方法可以帮助我,如果在不同的目录中有一些文件呢?例如,我想从 3 个不同的目录复制 3 个文件 嘿,我正在尝试从我的/roles/db/files 中移动所有文件,但我无法使用这种方法。我试过with_fileglob: - /roles/db/file/*,但路径不好 这种方法的最大缺点是它会使目录结构变平。【参考方案2】:
- name: Your copy task
  copy: src= item.src  dest= item.dest 
  with_items:
    -  src: 'containerizers', dest: '/etc/mesos/containerizers' 
    -  src: 'another_file', dest: '/etc/somewhere' 
    -  src: 'dynamic', dest: ' var_path ' 
  # more files here

【讨论】:

是否可以将此解决方案与dest 设置为变量? src: 'containerizers', dest: containerizers . @Gesias,是的。其实两边都可以是变量: src: ' source.var ', dest: ' dest.var ' 【参考方案3】:

从 Ansible 2.5 开始,应该使用 with_* 构造 are not recommended 和 loop 语法。一个简单实用的例子:

- name: Copy CA files
  copy:
    src: 'item'
    dest: '/etc/pki/ca-trust/source/anchors'
    owner: root
    group: root
    mode: 0644
  loop:
    - symantec-private.crt
    - verisignclass3g2.crt

【讨论】:

在page you linked 上明确表示with_* 已被弃用:“我们尚未弃用with_<lookup> - 该语法仍然适用于可预见的未来。” (截至 2021 年 11 月)他们只推荐它。 感谢您发现这一点 - 该通知之前不存在,它是在 2019 年末的某个时候添加的。将相应地修改答案。【参考方案4】:

你可以使用 with_together 来达到这个目的:

- name: Copy multiple files to multiple directories
  copy: src= item.0  dest= item.1 
  with_together:
    - [ 'file1', 'file2', 'file3' ]
    - [ '/dir1/', '/dir2/', '/dir3/' ]

【讨论】:

虽然它有效,但这在语义上并不干净 - 有更清洁的选项。【参考方案5】:

如果您需要多个位置,则需要多个任务。一个复制任务只能从一个位置(包括多个文件)复制到节点上的另一个位置。

- copy: src=/file1 dest=/destination/file1
- copy: src=/file2 dest=/destination/file2

# copy each file over that matches the given pattern
- copy: src= item  dest=/destination/
  with_fileglob:
    - /files/*

【讨论】:

- 名称:复制文件1 复制:src=/file1 dest=/destination/file1 - 名称:复制文件2 复制:src=/file2 dest=/destination/file2 视情况而定。更简单且可能更简洁,但可以使用更复杂的数据结构来完成,例如带有源数据和目标数据的匿名字典列表,用_items 循环。在任何语言中都是一样的——你必须做出判断。在某些情况下,委托函数比一长串复制/粘贴的 if 语句更有效且可维护。我是那种宁愿保持简洁的结构良好的代码而不是冗长乏味的几乎相同指令列表的怪胎,但我不认为每个人都同意。做你可以维护的事情。【参考方案6】:
- hosts: lnx
  tasks:
    - find: paths="/appl/scripts/inq" recurse=yes patterns="inq.Linux*"
      register: file_to_copy
    - copy: src= item.path  dest=/usr/local/sbin/
      owner: root
      mode: 0775
      with_items: " files_to_copy.files "

【讨论】:

请注意find 模块仅适用于 ansible 2.x,但不适用于 ansible 1.x 我已经修复了您的答案,因为您在返回值中提到了stdout_lines,但不适用于find 模块。它只有filesexaminedmatched 作为返回值。希望对其他人有所帮助 有人能够将文件复制到远程节点吗? find 似乎只查看远程系统,不允许从管理节点获取任何东西。这些答案,使用with_fileglob,似乎更合适:***.com/a/42290160/272387,***.com/a/36720342/272387。【参考方案7】:
- name: find inq.Linux*
  find:  paths="/appl/scripts/inq" recurse=yes patterns="inq.Linux*"
  register: find_files


- name: set fact
  set_fact:
    all_files:
      - " find_files.files | map(attribute='path') | list "
  when: find_files > 0


- name: copy files
  copy:
    src: " item "
    dest: /destination/
  with_items: " all_files "
  when: find_files > 0

【讨论】:

一个好的答案不仅包含代码,还包含一些解释或文档参考。 find、set_fact 和 copy 模块在 ansible 文档中都有解释。阅读有关过滤器的信息,如果您想了解有关本节的更多信息,也可以在 ansible 文档中了解 (- " find_files.files | map(attribute'path') | list ") Copy 假定本地源,所以为了使这个例子自洽,要么 find 选项需要在 localhost 上运行一次,否则最终的复制操作需要指定一个远程 src。这种方法的好处是它使文件列表可用于其他目的(例如,如果副本只是临时的,则稍后删除)。【参考方案8】:

或者你可以使用 with_items:

- copy:
    src: " item "
    dest: /etc/fooapp/
    owner: root
    mode: 600
  with_items:
    - dest_dir

【讨论】:

【参考方案9】:

copy 模块是复制许多文件和/或目录结构的错误工具,请使用synchronize 模块,而不是使用rsync 作为后端。请注意,它需要在控制器和目标主机上安装rsync。真的很强大,查看ansible documentation。

示例 - 将文件从控制器的build 目录(带有子目录)复制到目标主机上的/var/www/html 目录:

synchronize:
  src: ./my-static-web-page/build/
  dest: /var/www/html
  rsync_opts:
    - "--chmod=D2755,F644" # copy from windows - force permissions

【讨论】:

【参考方案10】:

您可以使用目录列表遍历变量:

- name: Copy files from several directories
  copy:
    src: " item "
    dest: "/etc/fooapp/"
    owner: root
    mode: "0600"
  loop: " files "
  vars:
    files:
      - "dir1/"
      - "dir2/"

【讨论】:

【参考方案11】:

使用以下源代码在您的客户端计算机上复制多个文件。


 - name: Copy data to the client machine
   hosts: hostname
   become_method: sudo
   become_user: root
   become: true
   tasks: 
     # Copy twice as sometimes files get skipped (mostly only one file skipped from a folder if the folder does not exist)
     - name: Copy UFO-Server 
       copy:
         src: "source files path"
         dest: "destination file path"
         owner: root
         group: root
         mode: 0644
         backup: yes
       ignore_errors: true

注意:

如果你使用变量传递多个路径,那么

src: "/root/ item "

如果您通过对不同项目使用变量来传递路径,那么

src: "/root/ item.source_path "

【讨论】:

【参考方案12】:

这里是复制文件的通用解决方案:

   ...
    - name: Find files you want to move
      ansible.builtin.find:
        paths: /path/to/files/
        file_type: file
        excludes: "*.txt" # Whatever pattern you want to exclude
      register: files_output

    - name: Copy the files
      ansible.builtin.copy:
        src: " item.path "
        dest: /destination/directory/
      loop: " files_output.files "
   ...

这比使用with_fileglob 更强大,因为您可以使用正则表达式进行匹配。下面是这个游戏的实际效果:

$ ls /path/to/files
demo.yaml  test.sh  ignore.txt

$ ls /destination/directory
file.h

$ ansible-playbook playbook.yaml
...[some output]...

$ ls /destination/directory
file.h demo.yaml test.sh

从上面的例子可以看出,ignore.txt 没有被复制到目标目录,因为 playbook 中的 excludes 正则表达式。仅使用with_fileglob 无法忽略此类文件。

此外,您可以相对轻松地从多个目录移动文件:

   ...
    - name: Find files you want to move
      ansible.builtin.find:
        paths: /path/to/files/
        # ... the rest of the task
      register: list1

    - name: Find more files you want to move
      ansible.builtin.find:
        paths: /different/path/
        # ... the rest of the task
      register: list2

    - name: Copy the files
      ansible.builtin.copy:
        src: " item.path "
        dest: /destination/directory/
      loop: " list1.files + list2.files "
   ...

【讨论】:

请添加更多细节,并添加一些示例。 @sorosh_sabz 应要求 ?【参考方案13】:

这是一个示例 Ansible 脚本,用于在远程主机上复制多个文件

名称:在远程主机上复制多个文件

ansible.windows.win_copy:

               src: " SrcPath / item" #Remeber to use item as a postfix to source path

               dest: "destPath"

               remote_src: yes [if Source Path available on remote Host]

               with_items:
                 - abc.txt
                 - abc.properties

【讨论】:

【参考方案14】:
主机:测试 收集事实:假 变成:真 变量: 路径:'/home/ansibm/playbooks' 远程路径:'/home/ansible_ssh_user' 目录:'yml_files' 任务: name: "为备份文件创建目录" 文件: 路径:' remote_path / dir ' 状态:目录 所有者:'ansible_ssh_user' 组:'ansible_ssh_user' 模式:0700 名称:“复制 yml 文件” 复制: 源代码:'item' dest: ' remote_path / dir ' 所有者:'ansible_ssh_user' 组:'ansible_ssh_user' 模式:0644 环形: - ' 路径 /ab.html' - ' 路径 /cp.yml'

【讨论】:

您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。【参考方案15】:

使用 Ansible 将文件从多个目录复制到多个目录

我发现guenhter 的答案很有帮助,但还需要更改远程文件的模式。我没有足够的声誉将此作为评论,这将是一个更合适的地方。在示例中,我将两个目录中的两个文件复制到 /tmp 和 /tmp/bin 中,我首先创建并修改远程文件模式。

- name: cpldupd
  hosts: test
  remote_user: root
  become: true
  vars:
    - rpth: /tmp
  tasks:
    - name: Create 'rpth/bin'
      file:
        path: 'rpth/bin'
        state: directory

    - name: Transfer
      copy: src= item.src  dest= item.dest  mode=0775
      with_items:
      -  src: '../utils/cpldupd', dest: 'rpth/cpldupd' 
      -  src: '../utils/bin/cpldupd', dest: 'rpth/bin/cpldupd' 

【讨论】:

如果您有新问题,请点击 按钮提出问题。如果有助于提供上下文,请包含指向此问题的链接。 - From Review 这不是一个问题,而是另一个使用 Ansible 将文件从多个目录复制到多个目录的更完整示例。它添加了远程文件模式。将其添加为评论可能更合适,但我还没有足够的声誉。我看到你过去也使用过这种技术***.com/questions/28347717/… 我有点苛刻,抱歉:当我审查这个问题时,感觉你想强调如何处理文件权限,但这不在原来的问题中(因此是一个新的问题)问题可能是突出这一点的好选择);你说得对,评论感觉更适合反对你提到的答案;我还看到使用mode 已经出现在其他几个答案中,所以不需要再说一遍。

以上是关于使用 Ansible 复制多个文件的主要内容,如果未能解决你的问题,请参考以下文章

升级到 1.9 后,使用 sudo 复制 Ansible 文件失败

每个主机上的 ansible 复制配置文件

如何相对于角色复制带有ansible的文件?

使用 Ansible 归档单个文件夹下的多个文件夹

如何使用 Ansible 将多个文件夹归档到一个文件夹下

ansible使用