LoginSignup
19
16

More than 5 years have passed since last update.

Ansibleでファイル・ディレクトリの存在確認

Last updated at Posted at 2019-02-07

この記事は

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ファイルを作成します。

chktest.yml
- 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

existsisregtrue になっています。
対象がディレクトリだった場合、isregではなく isdirtrue になります。

対象が存在しない場合のステータス

対象のファイルを削除して、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

出力がだいぶ少なくなりました。
existsfalse になっています。

実際に判定する場合

playbookファイルを作成します。

chkfile.yml
$ 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 の判定だけで終わっており、右側の isregisdir が判定されず 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
19
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
16