我需要在两个远程节点之间复制文件:
请注意,我运行所有 Ansible 任务的控制节点不是上述节点。
我尝试过以下方法:
在 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
这种方法会一直持续下去,永远不会结束。
使用
fetch
和 copy
模块
- 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
这种方法会引发如下错误:
访问文件 /Users//.ansible/cp/ansible-ssh-machine2-22- 时出错,错误为:[Errno 102] 套接字上不支持操作:u'/Users//.ansible/cp/ansible- ssh-machine2-22-'
我怎样才能实现这个目标?
正如 @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
。所以推(从ServerA
到ServerB
)确实是正确的方向。另请记住,我们不能简单地选择完全不委托,因为这意味着传输发生在控制节点和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
上执行的,因此拉动是正确的选择。
要复制远程到远程文件,您可以使用带有 synchronize
关键字的
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
此剧本可以从您的
machineC
运行。
如果您需要通过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
我能够使用 local_action to scp 将文件从机器 A 复制到机器 C,然后将文件复制到机器 B 来解决此问题。
如果您想进行 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
您也可以将
deletgate
与 scp
一起使用:
- 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
是其自身的文件。
使用复制模块将文件从一台服务器传输到另一台服务器的简单方法
这是剧本
---
- 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}
2021 年你应该安装包装器:
ansible-galaxy collection install ansible.posix
并使用
- name: Synchronize two directories on one remote host.
ansible.posix.synchronize:
src: /first/absolute/path
dest: /second/absolute/path
delegate_to: "{{ inventory_hostname }}"
了解更多:
https://docs.ansible.com/ansible/latest/collections/ansible/posix/synchronize_module.html
已检查:
ansible --version
ansible 2.10.5
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/daniel/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.9/site-packages/ansible
executable location = /sbin/ansible
python version = 3.9.1 (default, Dec 13 2020, 11:55:53) [GCC 10.2.0]
将系统机密从机器 1 传输到机器 2 时,您可能无法在它们之间直接访问,因此涉及
delegate_to
的解决方案将失败。当您将私钥保存在 ansible 控制节点上并将公钥保存在 machine1 和 machine2 的 ansible 用户帐户上的 ~/.ssh/authorized_keys
中时,就会发生这种情况。相反,您可以通过 ssh 将文件或目录从一台计算机传输到另一台计算机,使用无密码 sudo 进行远程权限升级:
-name "Copy /etc/secrets directory from machine1 and machine2"
delegate_to: localhost
shell: |
ssh machine1 sudo tar -C / -cpf - etc/secrets | ssh machine2 sudo tar -C / -xpf -
例如,要使用 MUNGE 守护进程进行身份验证来设置 ad hoc 计算集群,您可以使用以下命令将凭证从头节点复制到工作节点。
setup_worker.yml
- name: "Install worker packages"
apt:
name: "{{ packages }}"
vars:
packages:
- munge
# ...and other worker packages...
become: true
- name: "Copy MUNGE credentials from head to {{ host }}"
delegate_to: localhost
shell:
ssh head.domain.name sudo tar -C / -cpf - etc/munge | ssh {{ ansible_facts["nodename"] }} sudo tar -C / -xpf -
become: false
when: ansible_facts["nodename"] != "head.domain.name"
- name: "Restart MUNGE"
shell: |
systemctl restart munge
become: true
运行方式为
ansible-playbook -e host=machine1 setup_worker.yml
。
由于 ansible 用户没有特权,远程系统任务需要 become: true
。复制任务不需要提权,因为控制器仅用于设置管道;权限升级是通过 ssh 命令中的 sudo 进行的。变量 host
包含命令行上使用的主机模式,而不是正在初始化的工作程序。请改用 ansible_facts["nodename"]
,这将是当前工作线程的完全限定域名(假设工作线程已正确配置)。 when
子句阻止我们尝试将目录从头节点复制到自身上。