Usual Software Engineer

よくあるソフトウェアエンジニアのブログ

Ansible でリモートのファイルの内容を読み取る方法

はい。すいませんネタ切れですw 今回は小ネタも小ネタ、 Ansible の slurp モジュールについてです。 大して書くこともないので過去の Ansible の記事も貼っておきます。

innossh.hatenablog.com innossh.hatenablog.com innossh.hatenablog.com innossh.hatenablog.com

さて本題ですが、 Ansible を実行する際に対象のホスト上のファイルの内容を読み取って、その値を使って何か操作を行いたい時があります。例えば /var/log/message 内の特定のログを取得して、特定のサービスを再起動させたい、などでしょうか。 具体的な説明のために、今回は /etc/resolv.confnameserver を取得してみましょう。

何も考えずに playbook を書き始めるなら、単純に command, shell モジュールで grep を使うのがシンプルでしょうか。

  tasks:
    - name: retrieve nameserver
      shell: "grep nameserver /etc/resolv.conf | cut -d' ' -f2"
      register: nameserver
      changed_when: False

    - name: print nameserver
      debug:
        var: nameserver.stdout
TASK [print nameserver] *****************************************************************************************************************************
ok: [ansible-sandbox_echo1_1] => {
    "nameserver.stdout": "127.0.0.11"
}

ですが、もし専用のモジュールがあるなら command, shell モジュールを使うより良いですよね。 slurp モジュールというファイルの内容を読み取る機能があります。

slurp – Slurps a file from remote nodes — Ansible Documentation

slurp モジュールは次のように使います。

    - name: slurp resolv.conf
      slurp:
        src: /etc/resolv.conf
      register: resolv_conf

    - name: set nameserver
      set_fact:
        nameserver: "{{ resolv_conf.content | b64decode }}"

content は base64 エンコードされているので、 decode してあげる必要があります。 上記のままではただファイルの内容を nameserver の fact にセットしただけですので、 grep の時のように 127.0.0.11 をセットするには少しテクニックが必要です。

filter の regex_replace を使うのですが、ファイルの内容に改行を含んでいると複数行を考慮した置換ができません。 そのため次のように、はじめに改行を置換してしまいましょう。

  tasks:
    - name: slurp resolv.conf
      slurp:
        src: /etc/resolv.conf
      register: resolv_conf

    - name: set nameserver
      set_fact:
        nameserver: "{{ resolv_conf.content | b64decode | regex_replace('\n', ' ') | regex_replace('^.*nameserver ([^ ]+).*$', '\\1') }}"

    - name: print nameserver
      debug:
        var: nameserver
TASK [print nameserver] *****************************************************************************************************************************
ok: [ansible-sandbox_echo1_1] => {
    "nameserver": "127.0.0.11"
}

今回は改行をスペースに置換しましたが、 slurp するファイルによります。 このようにして shell モジュールと grep を使用しなくても、ファイルの内容の特定の値を取得することができます。 以上あまり使い所がない小ネタでした。