我正在运行一个 ansible 脚本来localhost
将文件夹复制到另一个位置。但是,
- name: Copy Network
become: yes
become_user: root
copy:
src: /d/
dest: "/dest/d/"
mode: 0644
tags: [network]
给了我[Errno 13] Permission denied: b'd/f1'
。我原本期望become_user
会让命令以 root 身份执行,但没有成功。此文件的权限是0600(root:root)
。
您能否给我指点一下如何使用 ansible 访问此文件并复制它?
笔记:
sudo ansible-playbook p.yml
sudo
运行完美,但是,如果不需要的话,我不想使用ansible 命令,并且 ansible 有一个技巧。command: cp -r /d/ /dest/d/
无需附加sudo
到 ansible 命令 (ansible-playbook p.yml
) 即可工作。但是,如果我可以帮助它,我不想使用command
它,因为幂等性 ©
模块具有mode
任务所需的选项。
答案1
更新:如果你可以将权限提升到 localhost master 上的 root 权限,解决方案是设置remote_src: true
(credit@ivandov)
- copy:
src: /d/
dest: /dest/d/
mode: '0644'
remote_src: true
become: true
become_user: root
以下详细信息描述了无法在本地主机上升级到 root 权限的情况。假设本地主机上的文件
shell> ll /tmp/test/d/f1
-rw-r----- 1 root root 0 Aug 25 23:23 /tmp/test/d/f1
模块复制按预期工作
- copy:
src: /tmp/test/d/
dest: /tmp/test/dest/
become: true
become_user: root
首先,它尝试读取文件但失败了
致命:[localhost]:失败!=> msg:'尝试读取文件“/tmp/test/d/f1”时发生错误:[Errno 13] 权限被拒绝:b''/tmp/test/d/f1''。[Errno 13] 权限被拒绝:b''/tmp/test/d/f1'''
默认情况下,模块复制复制文件自源码(要复制到远程服务器的文件的本地路径)目的地(文件应复制到的远程绝对路径)。在这种情况下,become: true
意味着 Ansible 会在远程主机上提升权限,但不会在本地主机主服务器上提升权限。尽管任务是在本地主机上运行,即主服务器和远程主机都是本地主机,但如果没有remote_src: true
设置,become: true
则仅适用于写入文件,而不适用于读取文件。如果您无法在本地主机设置上升级到 rootremote_src: true
- copy:
src: /tmp/test/d/
dest: /tmp/test/dest/
remote_src: true
become: true
become_user: root
将失败
致命:[localhost]:失败!=> 已更改 = false ansible_facts:discovered_interpreter_python:/usr/bin/python3 module_stderr:|- sudo:需要密码 module_stdout:'' msg:|- 模块失败 请参阅 stdout/stderr 以了解确切错误 rc:1
问:“有没有什么办法可以解决这个问题?”
答:如果不升级到根目录,就没有解决方法。这会违反文件的所有权和权限。例如,给定控制器中的文件
shell> ll f1
-rw-rw---- 1 root root 0 Sep 13 18:17 f1
下面的剧本是由非特权用户启动的
shell> cat playbook.yml
- hosts: test_01
become: true
tasks:
- copy:
src: f1
dest: /tmp
将会崩溃
TASK [copy] ****
fatal: [test_01]: FAILED! =>
msg: 'an error occurred while trying to read the file ''/scratch/f1'':
[Errno 13] Permission denied: b''/scratch/f1'''
如果您无法在本地主机主服务器上升级到 root 权限,则解决方案是使运行剧本的用户可读该文件。
答案2
根据弗拉基米尔的回答,实际上有一个简单的解决方法!
下面的评论(以及我用粗体添加的强调)是关键。
在模块复制中,变为:是仅适用于写入文件不读它。
只需使用remote_src: true
,即使您正在本地复制文件。这会导致在从本地计算机become
读取文件/目录时正确提升权限,因为它将 视为远程计算机并正确应用权限提升。src
src
- name: Copy Network
become: yes
become_user: root
copy:
src: /d/
dest: "/dest/d/"
remote_src: true # this allows become to work as expected
mode: 0644
tags: [network]
答案3
tl;dr - Ansiblebecome: root
适用于目标机器,而不是运行剧本的 Ansible 主机。可以采用变通方法。
我写了一个答案这里针对单个文件解决此问题:运行剧本的 Ansible 主机不会提升其自身的权限root
;become: root
这仅适用于目标机器。在原始问题中,两者都是,localhost
但我认为这种行为仍然适用,将其视为非特权root
“源”和root
特权目标。
该解决方案将delegate_to: localhost
所需slurp
的文件放入内存 - 使其delegate_to:
能够become: root
在本地发挥其魔力,然后将保存的文件写入目标机器。
然而,最初的问题询问是否对目录执行此操作:slurp
目录也已被讨论过这里与每个文件解决方案结合使用时,它应该提供一个合适的起点slurp
,尤其是注意@guzmonne 对该答案的评论。在slurp
使用每个文件的解决方法之前构建一个文件列表(这不是很好,但可能比改变文件/目录权限更好)。