この記事は
Ansibleのstatモジュールで、ファイル・ディレクトリの存在確認がどのように行えるかテストしています。
いつも忘れるので書き留めておきます。
2019年2月の時点で作業を行っています。
テストした環境
- CentOS Linux release 7.6.1810
- python version 2.7.5(
ansible --version
で表示された) - ansible 2.4.2.0
- ansible-playbook 2.4.2.0
取得できるステータスの確認方法
ファイル存在確認を行うには、statモジュールで対象のパスを指定します。
register: result
を記述することで、result変数にステータスが格納されます。
変数の値を判定することでファイルの存在確認を行います。
まずは、実際にどのようなステータスを受け取るのか確認します。
下記のplaybookファイルを作成します。
- hosts: 127.0.0.1
connection: local
gather_facts: False
tasks:
- name: check test
stat:
path: "test"
register: result
- name: debug
debug: var=result
対象がファイルの場合のステータス
対象のファイルを作成して、playbookを実行します。
$ touch test
$ ansible-playbook chktest.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note
that the implicit localhost does not match 'all'
PLAY [127.0.0.1] ***************************************************************
TASK [check test] **************************************************************
ok: [127.0.0.1]
TASK [debug result var] ********************************************************
ok: [localhost] => {
"result": {
"changed": false,
"failed": false,
"stat": {
-- 略 --
"exists": true,
-- 略 --
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
-- 略 --
}
}
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
exists
と isreg
が true
になっています。
対象がディレクトリだった場合、isreg
ではなく isdir
が true
になります。
対象が存在しない場合のステータス
対象のファイルを削除して、playbookを実行します。
$ rm test
$ ansible-playbook chktest.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note
that the implicit localhost does not match 'all'
PLAY [127.0.0.1] ***************************************************************
TASK [check test] **************************************************************
ok: [127.0.0.1]
TASK [debug result var] ********************************************************
ok: [localhost] => {
"result": {
"changed": false,
"failed": false,
"stat": {
"exists": false
}
}
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
出力がだいぶ少なくなりました。
exists
が false
になっています。
実際に判定する場合
playbookファイルを作成します。
$ cat chkfile.yml
- hosts: 127.0.0.1
connection: local
gather_facts: False
tasks:
- name: check test
stat:
path: "test"
register: chk_file
- name: isreg check
debug:
msg: "complete"
when: chk_file.stat.isreg == true
ignore_errors: yes
- name: isdir check
debug:
msg: "complete"
when: chk_file.stat.isdir == true
ignore_errors: yes
- name: exists check
debug:
msg: "complete"
when: chk_file.stat.exists == true
ignore_errors: yes
- name: exists and isreg check
debug:
msg: "complete"
when: chk_file.stat.exists == true and chk_file.stat.isreg == true
ignore_errors: yes
- name: exists and isdir check
debug:
msg: "complete"
when: chk_file.stat.exists == true and chk_file.stat.isdir == true
ignore_errors: yes
途中で FAILED
になっても止まらないように、ignore_errors: yes
をつけています。
対象がファイルの場合
対象のファイルを作成して、playbookを実行します。
$ touch test
$ ansible-playbook chkfile.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note
that the implicit localhost does not match 'all'
PLAY [127.0.0.1] ***************************************************************
TASK [check test] **************************************************************
ok: [127.0.0.1]
TASK [isreg check] *************************************************************
ok: [127.0.0.1] => {
"msg": "complete"
}
TASK [isdir check] *************************************************************
skipping: [127.0.0.1]
TASK [exists check] ************************************************************
ok: [127.0.0.1] => {
"msg": "complete"
}
TASK [exists and isreg check] **************************************************
ok: [127.0.0.1] => {
"msg": "complete"
}
TASK [exists and isdir check] **************************************************
skipping: [127.0.0.1]
PLAY RECAP *********************************************************************
127.0.0.1 : ok=4 changed=0 unreachable=0 failed=0
対象がファイルの場合に実行される判定方法
when: chk_file.stat.isreg == true
when: chk_file.stat.exists == true
when: chk_file.stat.exists == true and chk_file.stat.isreg == true
対象がファイルの場合にスキップされる判定方法
when: chk_file.stat.isdir == true
when: chk_file.stat.exists == true and chk_file.stat.isdir == true
対象がディレクトリの場合
対象のディレクトリを作成して、playbookを実行します。
$ rm test
$ mkdir test
$ ansible-playbook chkfile.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note
that the implicit localhost does not match 'all'
PLAY [127.0.0.1] ***************************************************************
TASK [check test] **************************************************************
ok: [127.0.0.1]
TASK [isreg check] *************************************************************
skipping: [127.0.0.1]
TASK [isdir check] *************************************************************
ok: [127.0.0.1] => {
"msg": "complete"
}
TASK [exists check] ************************************************************
ok: [127.0.0.1] => {
"msg": "complete"
}
TASK [exists and isreg check] **************************************************
skipping: [127.0.0.1]
TASK [exists and isdir check] **************************************************
ok: [127.0.0.1] => {
"msg": "complete"
}
PLAY RECAP *********************************************************************
127.0.0.1 : ok=4 changed=0 unreachable=0 failed=0
対象がディレクトリの場合に実行される判定方法
when: chk_file.stat.isdir == true
when: chk_file.stat.exists == true
when: chk_file.stat.exists == true and chk_file.stat.isdir == true
対象がディレクトリの場合にスキップされる判定方法
when: chk_file.stat.isreg == true
when: chk_file.stat.exists == true and chk_file.stat.isreg == true
対象が存在しない場合
対象のディレクトリを削除して、playbookを実行します。
$ rmdir test
$ ansible-playbook chkfile.yml
[WARNING]: provided hosts list is empty, only localhost is available. Note
that the implicit localhost does not match 'all'
PLAY [127.0.0.1] ***************************************************************
TASK [check test] **************************************************************
ok: [127.0.0.1]
TASK [isreg check] *************************************************************
fatal: [127.0.0.1]: FAILED! => {"msg": "The conditional check 'chk_file.stat.isreg == true' failed. The error was: error while evaluating conditional (chk_file.stat.isreg == true): 'dict object' has no attribute 'isreg'\n\nThe error appears to have been in '/root/chkfile.yml': line 11, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: isreg check\n ^ here\n"}
...ignoring
TASK [isdir check] *************************************************************
fatal: [127.0.0.1]: FAILED! => {"msg": "The conditional check 'chk_file.stat.isdir == true' failed. The error was: error while evaluating conditional (chk_file.stat.isdir == true): 'dict object' has no attribute 'isdir'\n\nThe error appears to have been in '/root/chkfile.yml': line 17, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: isdir check\n ^ here\n"}
...ignoring
TASK [exists check] ************************************************************
skipping: [127.0.0.1]
TASK [exists and isreg check] **************************************************
skipping: [127.0.0.1]
TASK [exists and isdir check] **************************************************
skipping: [127.0.0.1]
PLAY RECAP *********************************************************************
127.0.0.1 : ok=3 changed=0 unreachable=0 failed=0
対象が存在しない場合にスキップされる判定方法
when: chk_file.stat.exists == true
when: chk_file.stat.exists == true and chk_file.stat.isreg == true
when: chk_file.stat.exists == true and chk_file.stat.isdir == true
通常、存在しないステータスを判定すると FAILED
になります。
and
でつなげている時、左側の判定が false
だった場合は右側の式は判定されません。そのため、exists
の判定だけで終わっており、右側の isreg
やisdir
が判定されず FAILED
を回避しています。
対象が存在しない場合に失敗する判定方法
when: chk_file.stat.isreg == true
when: chk_file.stat.isdir == true
まとめ
解かりにくいので、表に。
対象が ファイル |
対象が ディレクトリ |
対象が 存在しない |
|
---|---|---|---|
chk_file.stat.isreg == true | 実行 | スキップ | 失敗 |
chk_file.stat.isdir == true | スキップ | 実行 | 失敗 |
chk_file.stat.exists == true | 実行 | 実行 | スキップ |
chk_file.stat.exists == true and chk_file.stat.isreg == true | 実行 | スキップ | スキップ |
chk_file.stat.exists == true and chk_file.stat.isdir == true | スキップ | 実行 | スキップ |
私の結論としては、対象が存在しなくても FAILED
にならない、以下の判定方法が良いのかなと。
when: chk_file.stat.exists == true
when: chk_file.stat.exists == true and chk_file.stat.isreg == true
when: chk_file.stat.exists == true and chk_file.stat.isdir == true