ansible-playbook で複数コマンド個別実行の結果を比較的スマートに表示する。


ansible 。ようやく手を出した。

ansible-playbook の場合、対象サーバの情報を抜き出して、表示させたいだけなのに、with_items で shell を
ループさせただけで、debug 時に他の雑多な情報に埋もれてしまう。

それだったら、シェルで for して、ansible をワンライナで叩いた方が見やすい。

、、、それで満足してたら進歩がないので、方法を探す。

実行

で、ぐぐったが、いい方法に当たらない、、、

仕方ないので、試行錯誤した挙句の果てが↓コレ。

test.yml
- hosts: root
  become: yes
  tasks:
    - shell: "{{ item }}"
      with_items:
        - 'echo first'
        - 'echo second'
        - 'echo third'
      register: result
    - debug: var="result.results.{{item}}.stdout_lines"
      with_sequence: start=0 end=2

with_items で回した場合の register は、変数名.results に蓄積されてく。

その内容には、配列っぽく 0, 1, 2 のインデクスでアクセス出来る。で、その配下に、 stdout_lines とか stderr_lines とかある訳で。

と言うことで、 index で回して、標準出力だけを表示させる。

$ ansible-playbook -i hosts test.yml

PLAY [root] ********************************************************************************************

TASK [Gathering Facts] *********************************************************************************
ok: [GUEST]

TASK [command] *****************************************************************************************
changed: [GUEST] => (item=echo first)
changed: [GUEST] => (item=echo second)
changed: [GUEST] => (item=echo third)

TASK [debug] *******************************************************************************************
ok: [GUEST] => (item=0) => {
    "item": 0,
    "result.results.0.stdout_lines": [
        "first"
    ]
}
ok: [GUEST] => (item=1) => {
    "item": 1,
    "result.results.1.stdout_lines": [
        "second"
    ]
}
ok: [GUEST] => (item=2) => {
    "item": 2,
    "result.results.2.stdout_lines": [
        "third"
    ]
}

PLAY RECAP *********************************************************************************************
GUEST                  : ok=3    changed=1    unreachable=0    failed=0

実用では、 name とかから、何のコマンドを実行したかを切り出すのは結構面倒なので、素直に - shell: 'echo WHAT_TO_DO ; WHAT_TO_DO' でお茶を濁す。

結果の加工

複数サーバを対象に実行した場合は、結果が入り乱れてしまうので、DEBUG の部分だけログから切り出して、

$ perl -F'(?=2018)' -0777lane 'print for map{ $_->[0] } sort { $a->[2] <=> $b->[2] or $a->[1] cmp $b->[1] } map { [ $_, (/\[(.*?)\].*?item=(\d+)/ )[0,1] ] } @F ' TEXT

でサクッと index 順 => サーバ順に並べなおして確認する、、、1


  1. もちろん、2018 が、stdout とかに含まれてたら、使えない。標準出力の方は、またちょっと違う。-F'(?=ok:)' に差し替えれば、動くと思う。やってないけど。