如何使用Ansible在两个节点之间复制文件


97

我需要将文件从机器A复制到机器B,而运行我所有可完成任务的控制机器是机器C(本地机器)

我尝试了以下方法:

在Ansible的Shell模块中使用scp命令

hosts: machine2
user: user2
tasks:
  - name: Copy file from machine1 to machine2 
    shell: scp user1@machine1:/path-of-file/file1 /home/user2/file1

这种方法永无止境。

使用提取和复制模块

hosts: machine1
user: user1
tasks:
  - name: copy file from machine1 to local
    fetch: src=/path-of-file/file1 dest=/path-of-file/file1

hosts: machine2
user: user2
tasks:
  - name: copy file from local to machine2
    copy: src=/path-of-file/file1 dest=/path-of-file/file1

这种方法给我抛出如下错误:

error while accessing the file /Users/<myusername>/.ansible/cp/ansible-ssh-machine2-22-<myusername>, error was: [Errno 102] Operation not supported on socket: u'/Users/<myusername>/.ansible/cp/ansible-ssh-machine2-22-<myusername>'

任何的意见都将会有帮助。


1.这是一项方便的功能,可以在控制机器距离较远时保存网络访问;2.Should现在是固定的每github.com/ansible/ansible/pull/16756 jctanner合并提交0d94d39到ansible:devel的在2016年9月23日
AnneTheAgile

Answers:


101

要复制远程文件,可以使用带有' '关键字的syncize模块delegate_to: source-server

- hosts: serverB
  tasks:    
   - name: Copy Remote-To-Remote (from serverA to serverB)
     synchronize: src=/copy/from_serverA dest=/copy/to_serverB
     delegate_to: serverA

该剧本可以在您的计算机上运行C。


好答案!不幸的是,我没有在多虚拟机的Vagrant环境中使用它。似乎Vagrant在这里做了一些特别的事情。
therealmarv

它使用rsync,您是否在vm上安装了它?
2015年

1
从Vagrant 1.7.x开始,它根据计算机使用不同的私钥。参见问题github.com/mitchellh/vagrant/issues/4967Vagrantfile中插入以下行,config.ssh.insert_key = false以强制Vagrant使用ONE insecure_key来访问所有机器。但是现在我什至没有收到错误消息(它会一直等待)。还有一个错误github.com/ansible/ansible/issues/7250表示不可能从远程复制到远程。
therealmarv

9
实际上,这会将文件从serverB复制到serverA。如果要将它们从serverA复制到serverB,请使用mode=push(或delegate_to: serverB,但不能同时使用两者)。
Marius Gedminas

2
@MariusGedminas是正确的,mode=push应该使用,但是在这种情况下delegate_to: serverB不能使用,因为那样会导致serverB源和目标。
Strahinja Kustudic '16

95

正如ant31已经指出的那样,您可以synchronize对此使用模块。默认情况下,模块在控制机器和当前远程主机(inventory_host)之间传输文件,但是可以使用任务的delegate_to参数进行更改(必须注意,这是任务的参数,而不是模块的参数)。

您可以将任务放在ServerA或上ServerB,但必须相应地调整传输方向(使用的mode参数synchronize)。

将任务放在 ServerB

- hosts: ServerB
  tasks:
    - name: Transfer file from ServerA to ServerB
      synchronize:
        src: /path/on/server_a
        dest: /path/on/server_b
      delegate_to: ServerA

这使用默认值mode: push,因此文件从委托(ServerA)传输到当前的远程(ServerB)。

这听起来很奇怪,因为任务已经ServerB通过(放置了hosts: ServerB)。但是,必须记住该任务实际上是在委托主机上执行的,在本例中为ServerA。因此,推动(从ServerAServerB)确实是正确的方向。还要记住,我们不能简单地选择根本不委托,因为那将意味着在控制机器和之间进行转移ServerB

将任务放在 ServerA

- hosts: ServerA
  tasks:
    - name: Transfer file from ServerA to ServerB
      synchronize:
        src: /path/on/server_a
        dest: /path/on/server_b
        mode: pull
      delegate_to: ServerB

这用于mode: pull反转传输方向。同样,请记住,任务实际上是在上执行的ServerB,因此拉动是正确的选择。


8
这是一个很好的答案,应该成为Ansible文档的一部分。那里的示例都没有如此清晰地说明这一点。谢谢!
ssc

2
我已经以多种方式尝试过此操作,但是,我没有通过Warning: Identity file /Users/myuser/.ssh/id_servers not accessible
orotemo '16

@orotemo:没有更多信息,我只能猜测,但这看起来像是您的SSH设置中的问题。请检查您是否已配置SSH或Ansible以使用错误消息中给出的身份文件,以及该文件是否存在并具有正确的权限。
弗洛里安·布鲁克

2
@WilliamTurrell我已经更新了答案,以更详细地说明转移方向。该模块确实有点令人困惑。
弗洛里安·布鲁克

1
谢谢。对于其他任何有@orotemo问题的人,可能的解决方案是您仅在服务器A和B之间没有任何公钥访问权限,或者正如我发现的那样,您已将其设置为仅在一个方向上工作-错误的方向。在服务器A的.ssh目录中没有任何密钥对的情况下,ansible尝试使用本地计算机的主目录(如果是Mac,该目录将不存在,并且可能具有不同的帐户名。)
威廉·特瑞尔16-10-20

2

我能够使用local_action解决此问题,将文件从machineA拷贝到machineC,然后将文件复制到machineB。


2

如果您需要通过Ansible在两个远程节点之间同步文件,则可以使用以下命令:

- name: synchronize between nodes
  environment:
    RSYNC_PASSWORD: "{{ input_user_password_if_needed }}"
  synchronize:
    src: rsync://user@remote_server:/module/
    dest: /destination/directory/
    // if needed
    rsync_opts:
       - "--include=what_needed"
       - "--exclude=**/**"
    mode: pull
    delegate_to: "{{ inventory_hostname }}"

启用时,remote_server需要使用守护程序模式启动rsync。简单的例子:

pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsync.log
port = port

[module]
path = /path/to/needed/directory/
uid = nobody
gid = nobody
read only = yes
list = yes
auth users = user
secrets file = /path/to/secret/file

1

一种使用复制模块将文件从一台服务器传输到另一台服务器的简单方法

这是剧本

---
- hosts: machine1 {from here file will be transferred to another remote machine}
  tasks:
  - name: transfer data from machine1 to machine2

    copy:
     src=/path/of/machine1

     dest=/path/of/machine2

    delegate_to: machine2 {file/data receiver machine}

这在今天的一次会议上浮出水面,但我们俩人都无法使用ansible 2.6.4进行复制。首先在machine1上创建文件并将此任务放到剧本中,然后再列出目录,此操作失败,并显示“在Ansible Controller上找不到或访问'/ tmp / source-49731914'”。在主机上创建一个空文件可以解决该问题,但是执行了host> machine2的复制。某些版本中可能存在儿童车行为?
斯蒂芬·B

0

如果要执行rsync并使用自定义用户和自定义ssh密钥,则需要在rsync选项中编写此密钥。

---
 - name: rsync
   hosts: serverA,serverB,serverC,serverD,serverE,serverF
   gather_facts: no
   vars:
     ansible_user: oracle
     ansible_ssh_private_key_file: ./mykey
     src_file: "/path/to/file.txt"
   tasks:
     - name: Copy Remote-To-Remote from serverA to server{B..F}
       synchronize:
           src:  "{{ src_file }}"
           dest: "{{ src_file }}"
           rsync_opts:
              - "-e ssh -i /remote/path/to/mykey"
       delegate_to: serverA

0

你可以用deletgatescp太:

- name: Copy file to another server
  become: true
  shell: "scp -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null admin@{{ inventory_hostname }}:/tmp/file.yml /tmp/file.yml"
  delegate_to: other.example.com

由于delegate该命令在另一台服务器上运行,因此它scp是文件本身。

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.