Я запускаю скрипт 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
ее, если могу помочь, из-за идемпотентности иcopy
у модуля естьmode
опция, необходимая для задачи.
решение1
Обновление: если вы можете повысить привилегии до root на локальном хосте master, то решение заключается в установке remote_src: true
(кредит @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
Сначала он пытается прочитать файл и терпит неудачу.
fatal: [localhost]: FAILED! => msg: 'произошла ошибка при попытке чтения файла ''/tmp/test/d/f1'': [Errno 13] Отказано в доступе: b''/tmp/test/d/f1'''. [Errno 13] Отказано в доступе: b''/tmp/test/d/f1'''
По умолчанию модулькопиякопирует файлы изисточник(локальный путь к файлу для копирования на удаленный сервер)место назначения(удаленный абсолютный путь, куда следует скопировать файл). В этом случае become: true
означает, что Ansible повышает привилегии на удаленном хосте, но не на локальном хосте master. Несмотря на то, что задача выполняется на localhost, т. е. и master, и удаленный хост являются localhost, без remote_src: true
настройки become: true
применяется только к записи файла, а не к его чтению. Если вы не можете повысить привилегии до root на локальном хосте, настройкаremote_src: true
- copy:
src: /tmp/test/d/
dest: /tmp/test/dest/
remote_src: true
become: true
become_user: root
не удастся
fatal: [localhost]: СБОЙ! => changed=false ansible_facts: discover_interpreter_python: /usr/bin/python3 module_stderr: |- sudo: требуется пароль module_stdout: '' msg: |- СБОЙ МОДУЛЯ Смотрите stdout/stderr для точного кода ошибки: 1
В:«Есть ли какое-то решение?»
A: Без эскалации до корня нет обходного пути. Это нарушит права собственности и разрешения файлов. Например, учитывая файл на контроллере
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
Основываясь на ответе Владимира, можно сказать, что на самом деле ЕСТЬ простое решение!
Комментарий ниже (и выделенный мной жирным шрифтом текст) был ключевым.
В модуле copy, become: yes применяется только к записи файлане читать это.
Просто используйте 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 - Ansible's become: root
применяется к целевой машине, а не к хосту Ansible, на котором запущен плейбук. Возможны обходные пути.
Я написал ответздесьчтобы решить эту проблему для одного файла: Хост Ansible, на котором запущена книга сценариев, не повышает свои собственные разрешения для root
with become: root
; это относится только к целевой машине. В исходном вопросе оба варианта, localhost
но я думаю, что это поведение все еще применимо, думайте о нем как о непривилегированном root
«источнике» и root
привилегированной цели.
Решение использует delegate_to: localhost
для сохранения slurp
необходимого файла в памяти, что delegate_to:
позволяет become: root
работать локально, а затем записывать сохраненный файл на целевую машину.
Однако в исходном вопросе спрашивается о том, как это сделать для каталогов: slurp
ing directorys также обсуждалосьздесьчто должно обеспечить подходящую отправную точку в сочетании с решением для каждого файла slurp
, особенно обратите внимание на комментарий @guzmonne к этому ответу относительно создания списка файлов перед slurp
использованием обходного пути для каждого файла (что не очень хорошо, но может быть предпочтительнее изменения прав доступа к файлам/каталогам).