Checking File Last Change Date with Ansible

![banner-ansible.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/1132c513-9e08-b4c7-10b9-9e2d2a7bc279.png)

> Share how you can use Ansible to check the last modified date of a file.
> I wrote each of `ad-hoc` and `playbook` methods.

## Test environment
- 1 master (Ubuntu 18.04), 2 child (CentOS7, Debian8)
- [Ansible2.9.2](https://qiita.com/leechungkyu/items/1b49a970e1facdc38d0a)

```bash:/etc/ansible/hosts
[child]
182.252.133.71
182.252.133.72

[child:vars]
ansible_user=root
ansible_password=Password123!
```

## Scenario 1
Prints the last modified date of the server `/etc/passwd` file on child01, child02.
### ad-hoc
Command

```bash
$ ansible child -m shell -a 'stat -c "%y" /etc/passwd |cut -f1 -d" "'
```
Result

```bash
root@master:/workspace/ansible# ansible child -m shell -a 'stat -c "%y" /etc/passwd |cut -f1 -d" "'
[WARNING]: Platform linux on host 182.252.133.72 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python
interpreter could change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.

182.252.133.72 | CHANGED | rc=0 >>
2017-08-04

182.252.133.71 | CHANGED | rc=0 >>
2020-02-03
```


### playbook
`mtime_file.yml` and `my_filter.py` are required.

```bash
├── filter_plugins
│   ├── my_filter.py
│   └── my_filter.pyc
└── mtime_file.yml
```
```bash:mtime_file.yml
---
- hosts : child
  tasks :
  - name: Check the passwd file change date
    stat: path=/etc/passwd
    register : status_file

  - debug :
      var : status_file.stat.mtime | my_filter
    when : status_file.stat.exists

```
```bash:./filter_plugins/my_filter.py
import datetime

def my_filter(arg):
    value = datetime.datetime.utcfromtimestamp(arg).strftime('%Y-%m-%d')
    return value

class FilterModule(object):
    def filters(self):
        return { 'my_filter': my_filter }

```
Command

```bash
$ ansible-playbook ./mtime_file.yml
```
Result

```bash
root@master:/workspace/ansible# ansible-playbook ./mtime_file.yml

PLAY [child] *****************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************
ok: [182.252.133.71]
ok: [182.252.133.72]

TASK [Check the passwd file change date] ****************************************************************************************************************************************
ok: [182.252.133.72]
ok: [182.252.133.71]

TASK [debug] *****************************************************************************************************************************************************
ok: [182.252.133.72] => {
    "status_file.stat.mtime | my_filter": "2017-08-04"
}
ok: [182.252.133.71] => {
    "status_file.stat.mtime | my_filter": "2020-02-03"
}

PLAY RECAP *******************************************************************************************************************************************************
182.252.133.71             : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
182.252.133.72             : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
```

## Scenario 2
Prints the last modified date of the server `/etc/passwd.bak` file on child01, child02.
`/etc/passwd.bak` is a file that exists only in child01.

### ad-hoc
Command

```bash
$ ansible child -m shell -a 'stat -c "%y" /etc/passwd.bak |cut -f1 -d" "'
```
Result

```bash
root@master:/workspace/ansible# ansible child -m shell -a 'stat -c "%y" /etc/passwd.bak |cut -f1 -d" "'
[WARNING]: Platform linux on host 182.252.133.72 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python
interpreter could change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.

182.252.133.72 | CHANGED | rc=0 >>
stat: cannot stat ‘/etc/passwd.bak’: No such file or directory

182.252.133.71 | CHANGED | rc=0 >>
2019-02-12
```


### playbook
`mtime_file.yml` and `my_filter.py` are required.

```bash
├── filter_plugins
│   ├── my_filter.py
│   └── my_filter.pyc
└── mtime_file.yml
```
```bash:mtime_file.yml
---
- hosts : child
  tasks :
  - name: Check the passwd.bak file change date
    stat: path=/etc/passwd
    register : status_file

  - debug :
      var : status_file.stat.mtime | my_filter
    when : status_file.stat.exists

```
```bash:./filter_plugins/my_filter.py
import datetime

def my_filter(arg):
    value = datetime.datetime.utcfromtimestamp(arg).strftime('%Y-%m-%d')
    return value

class FilterModule(object):
    def filters(self):
        return { 'my_filter': my_filter }

```
Command

```bash
$ ansible-playbook ./mtime_file.yml
```
Result

```bash
root@master:/workspace/ansible# ansible-playbook ./mtime_file.yml

PLAY [child] *****************************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************
ok: [182.252.133.72]
ok: [182.252.133.71]

TASK [Check the passwd.bak file change date] ****************************************************************************************************************************************
ok: [182.252.133.72]
ok: [182.252.133.71]

TASK [debug] *****************************************************************************************************************************************************
ok: [182.252.133.71] => {
    "status_file.stat.mtime | my_filter": "2019-02-12"
}
skipping: [182.252.133.72]

PLAY RECAP *******************************************************************************************************************************************************
182.252.133.71             : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
182.252.133.72             : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
```

## Lesson
I used ansible mostly for collecting server information.
The parsing of the resulting screen was necessary for the collection, whether `ad-hoc` or `playbook`

> In the case of `ad-hoc`, normal operation was checked with `rc=0` and `rc=1` in the result.
> As in scenario 2, it may not be normal operation even if `rc=0` is included.

> In the case of `playbook `, I can check the normal operation with `ok:` and `skipping:` on result.  

As far as possible, ansible scripts should be written in playbook.