Ansible 复制模块 & 成为 - 权限被拒绝

Ansible 复制模块 & 成为 - 权限被拒绝

我正在运行一个 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.ymlsudo运行完美,但是,如果不需要的话,我不想使用ansible 命令,并且 ansible 有一个技巧。

  • command: cp -r /d/ /dest/d/无需附加sudo到 ansible 命令 ( ansible-playbook p.yml) 即可工作。但是,如果我可以帮助它,我不想使用command它,因为幂等性 &copy模块具有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读取文件/目录时正确提升权限,因为它将 视为远程计算机并正确应用权限提升。srcsrc

- 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 主机不会提升其自身的权限rootbecome: root这仅适用于目标机器。在原始问题中,两者都是,localhost但我认为这种行为仍然适用,将其视为非特权root“源”和root特权目标。

该解决方案将delegate_to: localhost所需slurp的文件放入内存 - 使其delegate_to:能够become: root在本地发挥其魔力,然后将保存的文件写入目标机器。

然而,最初的问题询问是否对目录执行此操作:slurp目录也已被讨论过这里与每个文件解决方案结合使用时,它应该提供一个合适的起点slurp,尤其是注意@guzmonne 对该答案的评论。在slurp使用每个文件的解决方法之前构建一个文件列表(这不是很好,但可能比改变文件/目录权限更好)。

相关内容