localhost
フォルダを別の場所にコピーするためにAnsibleスクリプトを実行しています。しかし、
- 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'
。このコマンドが root として実行されることを期待していましたがbecome_user
、動作しませんでした。このファイルの権限は です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
更新: ローカルホストマスターで権限をルートに昇格できる場合、解決策は次のようになりますremote_src: true
(credit @ivandov)
- copy:
src: /d/
dest: /dest/d/
mode: '0644'
remote_src: true
become: true
become_user: 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]: 失敗しました! => メッセージ: 'ファイル ''/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
と、ファイルの書き込みにのみ適用され、読み取りには適用されません。ローカルホスト設定でルートに昇格できない場合は、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: discovered_interpreter_python: /usr/bin/python3 module_stderr: |- sudo: パスワードが必要です module_stdout: '' msg: |- モジュール障害 正確なエラーについては stdout/stderr を参照してください rc: 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'''
ローカルホスト マスターでルートにエスカレートできない場合は、プレイブックを実行しているユーザーがファイルを読み取り可能にすることが解決策です。
答え2
Vladimir の回答を基にすると、実は簡単な回避策があります。
以下のコメント(太字で強調した部分)が鍵でした。
モジュールコピーでは、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 は、become: root
プレイブックを実行している Ansible ホストではなく、ターゲット マシンに適用されます。回避策は可能です。
答えを書きましたここroot
単一ファイルでこの問題に対処するには、プレイブックを実行している Ansible ホストは、で自身の権限を に上げませんbecome: root
。これはターゲット マシンにのみ適用されます。元の質問では両方とも ですが、この動作は依然として適用されると思います。これは、権限のない「ソース」と権限のあるターゲットlocalhost
として考えてください。root
root
このソリューションdelegate_to: localhost
では、slurp
必要なファイルをメモリに保存します。これにより、ローカルでその魔法が動作し、保存されたファイルをターゲット マシンに書き出すdelegate_to:
ことができます。become: root
元の質問では、ディレクトリに対してこれを行うことについて尋ねていますが、slurp
ディレクトリについても議論されています。こここれは、ファイルごとのソリューションと組み合わせると適切な出発点となるはずですslurp
。特に、ファイルごとの回避策を使用する前にファイルのリストを作成することに関する、その回答に対する @guzmonne のコメントに注意してくださいslurp
(これは優れた方法ではありませんが、ファイル/ディレクトリのアクセス許可を変更するよりも好ましい場合があります)。