質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Ansible

Ansibleは、Python で書かれたサーバーの設定を管理するための 構成管理ツールです。

Q&A

解決済

1回答

247閲覧

Ansible 1タスク内で複数ファイルの有無確認を行い、存在する場合には同時に複数ファイルを削除したい

khaii21

総合スコア66

Ansible

Ansibleは、Python で書かれたサーバーの設定を管理するための 構成管理ツールです。

0グッド

0クリップ

投稿2024/03/15 23:07

編集2024/03/17 06:18

実現したいこと

statモジュールで対象ファイルの有無確認を行い、変数(stat.exists)の結果がtrueの場合に
①のタスクにて複数のファイルを同時に削除をしたいです。
対象ファイルは複数あるため、loopやwith_itemsを使って1タスク内で複数のファイルの有無を
同時にチェックして存在するファイルは削除したいです。

①のように"path"に対して1ファイルだけを設定してstatモジュールでチェックした場合、
変数(hoge_check.stat.exists)はbool型であるためファイルの有無がチェックできますが、
②のようにloop処理で"path"に対して複数のファイルを通す場合、
変数(hoge_check.stat.exists)は"VARIABLE IS NOT DEFINED!"となります。

変数(hoge_check.stat.exists)は、

'dict object' has no attribute 'stat'. 'dict object' has no attribute 'stat'

となり値が存在しない結果となります。
変数(hoge_check)を確認すると③の結果となっており、変数(hoge_check.results)はlist型であるため、stat.existsによるtrue/falseが確認出来ません。
1タスク内で複数のファイルの有無をチェックして、存在する場合に削除する方法はありますでしょうか。

fileモジュールのstateにabsentを設定すればファイルが無い場合には何もしないので
有無チェックは本来不要ですが、どのようにすれば有無チェック出来るのか知りたいです。

発生している問題・エラーメッセージ

fatal: [localhost]: FAILED! => {"msg": "The conditional check 'hoge_check.stat.exists' failed. The error was: error while evaluating conditional (hoge_check.stat.exists): 'dict object' has no attribute 'stat'. 'dict object' has no attribute 'stat'\n\nThe error appears to be in '/hoge/hoge2.yml: line 15, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n- name: Check hoge_web.log\n ^ here\n"}

該当のソースコード

# 本来は下記のように複数ファイルの有無を同時にチェックして複数存在する場合は同時に削除したい - name: Check hoge_web.log ansible.builtin.stat: path: "{{ task_dir }}/hoge_hoge/{{ item }}" register: hoge_check loop: - "hoge1.log" - "hoge2.log" - name: Delete hoge_web.log ansible.builtin.file: path: "{{ task_dir }}/hoge_hoge/{{ item }}" state: absent loop: - "hoge1.log" - "hoge2.log" when: hoge_check.stat.exists

- name: Check hoge_web.log ansible.builtin.stat: path: "{{ task_dir }}/hoge_hoge/hoge1.log" register: hoge_check - name: Result hoge_web.log ansible.builtin.debug: var: hoge_check.stat.exists

結果

# var: hoge_check.stat.exists ok: [localhost] => { "hoge_check.stat.exists": true } # msg: hoge_check.stat.exists ok: [localhost] => { "msg": "bool" }

- name: Check hoge_web.log ansible.builtin.stat: path: "{{ task_dir }}/hoge_hoge/{{ item }}" loop: - "hoge1.log" - "hoge2.log" register: hoge_check - name: Result hoge_web.log ansible.builtin.debug: msg: hoge_check.results

結果

# var: hoge_check.stat.exists ok: [localhost] => { "hoge_check.stat.exists": "VARIABLE IS NOT DEFIND!" }
# msg: "{{ hoge_check.results | type_debug }}" ok: [localhost] => { "msg": "list" }

hoge.yml

1- name: Check hoge_web.log 2 ansible.builtin.stat: 3 path: "{{ task_dir }}/hoge_hoge/{{ item }}" 4 register: hoge_check 5 loop: 6 - "hoge1.log" 7 - "hoge2.log" 8 9- name: Delete hoge_web.log 10 ansible.builtin.file: 11 path: "{{ task_dir }}/hoge_hoge/{{ item }}" 12 state: absent 13 register: check_loop ・ 1415 loop: 16 - "hoge_check.results" 17 when:

Delete hoge_web.logタスクの結果

# 下記の「Check hoge_web.logタスクのitemに渡される一覧の抜粋」が次々と渡されている様子 ok: [localhost] => (item=[{'invocation': {'module_args': {'checksum_algorithm': 'sha1', 'get_checksum': True, 'follow': False, 'path': '/home/hoge_hoge/hoge1.log', 'get_md5': False, 'get_mime': True, 'get_attributes': True}}, 'stat': {'charset': 'binary', 'uid': 0, 'exists': True, 'attr_flags': 'e', 'woth': False, 'isreg': True, 'device_type': 0, 'mtime': 1710652113.4640188, 'block_size': 4096, 'inode': 2416182, 'isgid': False, 'size': 1219, 'executable': False, 'roth': True, 'isuid': False, 'readable': True, 'version': '1282907058', 'pw_name': 'root', 'gid': 0, 'ischr': False, 'wusr': True, 'writeable': True, 'isdir': False, 'blocks': 8, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'root', 'path': '/home/hoge_hoge/hoge1.log', 'xusr': False, 'atime': 1710627251.1956754, 'mimetype': 'application/octet-stream', 'ctime': 1710652113.4640188, 'isblk': False, 'checksum': '4・・1b55・・・49a3d・・', 'dev': 64513, 'wgrp': False, 'isfifo': False, 'mode': '0644', 'xgrp': False, 'islnk': False, 'attributes': ['extents']}, 'changed': False, 'failed': False, 'item': 'saveMessage.log', 'ansible_loop_var': 'item'}, {'invocation': {'module_args': {'checksum_algorithm': 'sha1', 'get_checksum': True, 'follow': False, 'path': '/home/hoge_hoge/hoge2.log', 'get_md5': False, 'get_mime': True, 'get_attributes': True}}, 'stat': {'charset': 'us-ascii', 'uid': 0, 'exists': True, 'attr_flags': 'e', 'woth': False, 'isreg': True, 'device_type': 0, 'mtime': 1710652114.3400238, 'block_size': 4096, 'inode': 2416199, 'isgid': False, 'size': 1189, 'executable': False, 'roth': True, 'isuid': False, 'readable': True, 'version': '1282907076', 'pw_name': 'root', 'gid': 0, 'ischr': False, 'wusr': True, 'writeable': True, 'isdir': False, 'blocks': 8, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'root', 'path': '/home/hoge_hoge/hoge2.log', 'xusr': False, 'atime': 1710627252.0996804, 'mimetype': 'text/plain', 'ctime': 1710652114.3400238, 'isblk': False, 'checksum': '960b・・・deb55337b07', 'dev': 64513, 'wgrp': False, 'isfifo': False, 'mode': '0644', 'xgrp': False, 'islnk': False, 'attributes': ['extents']}, 'changed': False, 'failed': False, 'item': 'hoge2.log', 'ansible_loop_var': 'item'}])

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

comefigo

2024/03/16 14:01

loopの結果が格納されている`hoge_check.results`はリストなので、それをloopしましょう。
khaii21

2024/03/17 07:26 編集

コメントありがとうございます。 大変助かりました。
guest

回答1

0

ベストアンサー

loop するタスクの実行結果を register で取得する場合、loop しない場合とでデータ構造が変わるのがポイントです。前者の場合、いただいた例では hoge_check.results 配下にリストとして item ごとの実行結果が格納されます。

ですので、ファイルの削除タスクでは hoge_check.results を loop させて、when ステートメントもこれにあわせた定義にすると複数ファイルに対応してファイルの有無によるロジックを記述できるかと思います。

トラブルシュートする際は、ansible.builtin.debugvar パラメータなどを積極的に活用して変数のデータ構造を確認する習慣をつけるとこの手の問題に悩まされることも少なくなると思いますのでオススメです。

以下のような感じですね。ご参考になれば幸いです。

yaml

1--- 2- hosts: localhost 3 gather_facts: false 4 tasks: 5 - ansible.builtin.stat: 6 path: "hoge_hoge/{{ item }}" 7 register: hoge_check 8 loop: 9 - "hoge1.log" 10 - "hoge2.log" 11 12 - ansible.builtin.debug: 13 var: hoge_check

実行結果

shell

1$ ansible-playbook test.yml 2[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' 3 4PLAY [localhost] *********************************************************************************************************************************************************************************** 5 6TASK [ansible.builtin.stat] ************************************************************************************************************************************************************************ 7ok: [localhost] => (item=hoge1.log) 8ok: [localhost] => (item=hoge2.log) 9 10TASK [ansible.builtin.debug] *********************************************************************************************************************************************************************** 11ok: [localhost] => { 12 "hoge_check": { 13 "changed": false, 14 "msg": "All items completed", 15 "results": [ 16 { 17 "ansible_loop_var": "item", 18 "changed": false, 19 "failed": false, 20 "invocation": { 21 "module_args": { 22 "checksum_algorithm": "sha1", 23 "follow": false, 24 "get_attributes": true, 25 "get_checksum": true, 26 "get_md5": false, 27 "get_mime": true, 28 "path": "hoge_hoge/hoge1.log" 29 } 30 }, 31 "item": "hoge1.log", 32 "stat": { 33 "atime": 1710638919.5081928, 34 "attr_flags": "", 35(...) 36 "exists": true, 37(...) 38 "xusr": false 39 } 40 }, 41 { 42 "ansible_loop_var": "item", 43 "changed": false, 44 "failed": false, 45 "invocation": { 46 "module_args": { 47 "checksum_algorithm": "sha1", 48 "follow": false, 49 "get_attributes": true, 50 "get_checksum": true, 51 "get_md5": false, 52 "get_mime": true, 53 "path": "hoge_hoge/hoge2.log" 54 } 55 }, 56 "item": "hoge2.log", 57 "stat": { 58 "atime": 1710638919.8352227, 59 "attr_flags": "", 60(...) 61 "exists": true, 62(...) 63 "xoth": false, 64 "xusr": false 65 } 66 } 67 ], 68 "skipped": false 69 } 70} 71

追記1:

コメントいただいた部分に回答しますね。
hoge.yml についての修正箇所は...

  • 11行目: fileモジュールの path パラメータは、前タスクの stat モジュールの実行結果から item.stat.path を参照する
  • 12行目: state パラメータのインデントを修正
  • 16行目: ダブルクォーテーションだけでは文字列として評価されてしまうため、 "{{ hoge_check.results }}" の形で変数を参照する
  • 17行目: when ステートメントの定義がないので、それを追加する

っで、以下のような感じでしょうか。2つのファイルのうち、片方は存在する、もう片方は存在しないパターンで試してみました。

yaml

1--- 2- hosts: localhost 3 gather_facts: false 4 tasks: 5 - ansible.builtin.stat: 6 path: "hoge_hoge/{{ item }}" 7 register: hoge_check 8 loop: 9 - "hoge1.log" # 存在する 10 - "hoge2.log" # 存在しない 11 12 - ansible.builtin.file: 13 path: "{{ item.stat.path }}" 14 state: absent 15 loop: "{{ hoge_check.results }}" 16 when: item.stat.exists

実行結果

shell

1]$ ansible-playbook test.yml 2[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all' 3 4PLAY [localhost] *********************************************************************************************************************************************************************************** 5 6TASK [ansible.builtin.stat] ************************************************************************************************************************************************************************ 7ok: [localhost] => (item=hoge1.log) 8ok: [localhost] => (item=hoge2.log) 9 10TASK [ansible.builtin.file] ************************************************************************************************************************************************************************ 11changed: [localhost] => (item={'changed': False, 'stat': {'exists': True, 'path': 'hoge_hoge/hoge1.log', (...) , 'failed': False, 'item': 'hoge1.log', 'ansible_loop_var': 'item'}) 12skipping: [localhost] => (item={'changed': False, 'stat': {'exists': False}, (...) , 'failed': False, 'item': 'hoge2.log', 'ansible_loop_var': 'item'}) 13 14PLAY RECAP ***************************************************************************************************************************************************************************************** 15localhost : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

投稿2024/03/17 01:42

編集2024/03/17 07:24
__kina

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

khaii21

2024/03/17 06:16 編集

ご回答ありがとうございます。 きちんと認識出来ておらず申し訳ございません。 宜しければ幾つか伺わせて頂けないでしょうか。 該当のソースコード欄の④hoge.ymlを追記させて頂きました。 「Delete hoge_web.log」タスクでloopの対象(hoge_check.results)に設定。 タスクを実行すると、itemに渡される一覧が出力されます。 変数itamに渡された結果は「Delete hoge_web.logタスクの結果」となりました。 17行目のwhen句に設定する条件が検討がついておらずファイルが削除出来ません。 またhoge_check.resultsをloopさせるやり方に誤りがあると思いますが、何かお気づきの事がありましたらご指摘頂けないでしょうか。hoge_check.resultsflist型になりますので、「hoge_check.results.item」を指定すると"VARIABLE IS NOT DEFINED!"になってしまいます。
__kina

2024/03/17 07:23

回答に追記しましたのでご確認くださいませー!
khaii21

2024/03/17 07:25

色々とご確認ありがとうございました。 やりたいことが実現出来ました。 大変助かりました。
__kina

2024/03/17 07:30

いえいえー
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問