LoginSignup
78
79

More than 5 years have passed since last update.

ansibleでの実行結果のsuccess/failedとignore_errors/failed_whenがよくわからなかったので調べてみた

Last updated at Posted at 2015-05-12

知りたいこと

  • ansibleでのsuccessとfailedの判定
  • それをハンドリングするための ignore_errors と failed_when の使い方

事前実験

存在しないコマンドを実行してみる

ansibleでの接続先(リモートサーバー。CentOS6)で `sakaimo --version' コマンドしてみる。ちなみに現時点のsakaimoのversionは39.7くらいのはず。

# sakaimo --version
-bash: sakaimo: command not found

CentOSさんにはこんなコマンドは存在しないのでnot foundになります。

ansibleでやってみる

playbook

- shell: sakaimo --version

- debug: msg="debug"

実行結果

PLAY [app] ********************************************************************

TASK: [sakaimo| shell sakaimo --version] *************************************
failed: [qa-lecture01] => {"changed": true, "cmd": "sakaimo --version", "delta": "0:00:00.146319", "end": "2015-05-12 10:52:53.548610", "rc": 127, "start": "2015-05-12 10:52:53.402291", "warnings": []}
stderr: /bin/sh: sakaimo: command not found

FATAL: all hosts have already failed -- aborting

PLAY RECAP ********************************************************************
           to retry, use: --limit @/root/qa-lecture-playbook.retry

qa-lecture01               : ok=0    changed=0    unreachable=0    failed=1

一つ目でエラーが出た場合に- debug: msg="debug"は実行されていないことがわかります。しれっと「エラーが出た場合」と言っていますが、何がansibleで「エラー」と判定されるのかどうかを知りたくて調べてるんですけどねw

ignore_errors

ignore_errorsを付けてみる。

playbook

- shell: sakaimo --version
  ignore_errors: True #←ここ

- debug: msg="debug"

出力結果

PLAY [app] ********************************************************************

TASK: [sakaimo | shell sakaimo --version] *************************************
failed: [qa-lecture01] => {"changed": true, "cmd": "sakaimo --version", "delta": "0:00:00.143888", "end": "2015-05-12 10:53:30.886426", "rc": 127, "start": "2015-05-12 10:53:30.742538", "warnings": []}
stderr: /bin/sh: sakaimo: command not found
...ignoring

TASK: [sakaimo | debug msg="debug"] ****************************************
ok: [qa-lecture01] => {
    "msg": "debug"
}

PLAY RECAP ********************************************************************
qa-lecture01               : ok=2    changed=1    unreachable=0    failed=0

ignore_errors: Trueでは文字通りエラーがあっても無視して先にすすんでくれるようです。(debugが出力されているから) つまりcommand not foundはエラーとして認識されるみたいね。

実行結果によって分岐させてみる

when: result|failedを付けてみた。

playbook

- shell: sakaimo --version
  register: result
  ignore_errors: True

- debug: msg="debug"
  when: result|failed #←ここ

実行結果

PLAY [app] ********************************************************************

TASK: [sakaimo | shell sakaimo --version] *************************************
failed: [qa-lecture01] => {"changed": true, "cmd": "sakaimo --version", "delta": "0:00:00.142611", "end": "2015-05-12 11:00:33.019179", "rc": 127, "start": "2015-05-12 11:00:32.876568", "warnings": []}
stderr: /bin/sh: sakaimo: command not found
...ignoring

TASK: [sakaimo | debug msg="debug"] ****************************************
ok: [qa-lecture01] => {
    "msg": "debug"
}

PLAY RECAP ********************************************************************
qa-lecture01               : ok=2    changed=1    unreachable=0    failed=0

failedをsuccessにしてみたplaybook

- shell: sakaimo --version
  register: result
  ignore_errors: True

- debug: msg="debug"
  when: result|success #←ここ

実行結果

PLAY [app] ********************************************************************

TASK: [sakaimo | shell sakaimo --version] *************************************
failed: [qa-lecture01] => {"changed": true, "cmd": "sakaimo --version", "delta": "0:00:00.144219", "end": "2015-05-12 11:01:29.798585", "rc": 127, "start": "2015-05-12 11:01:29.654366", "warnings": []}
stderr: /bin/sh: sakaimo: command not found
...ignoring

TASK: [sakaimo | debug msg="debug"] ****************************************
skipping: [qa-lecture01]

PLAY RECAP ********************************************************************
qa-lecture01               : ok=1    changed=1    unreachable=0    failed=0

resultがfailedなので、debugがskipされています。ということはcommand not foundは'failed'と判定されるということね。

TASK: [sakaimo | debug msg="debug"] ****************************************
skipping: [qa-lecture01]

では成功するコマンドだったらどうなるのか。unameコマンドで実験。

リモートサーバーでの実行結果は

# uname
Linux

になってます。

playbook

- shell: uname
  register: result
  ignore_errors: True

- debug: msg="debug"
  when: result|success

実行結果

PLAY [app] ********************************************************************

TASK: [sakaimo | shell uname] *************************************************
changed: [qa-lecture01]

TASK: [sakaimo | debug msg="debug"] *******************************************
ok: [qa-lecture01] => {
    "msg": "debug"
}

PLAY RECAP ********************************************************************
qa-lecture01               : ok=2    changed=1    unreachable=0    failed=0

successをfailedにしてみる

playbook

- shell: uname
  register: result
  ignore_errors: True

- debug: msg="debug"
  when: result|failed #←ここ

実行結果

PLAY [app] ********************************************************************

TASK: [sakaimo | shell uname] *************************************************
changed: [qa-lecture01]

TASK: [sakaimo | debug msg="debug"] *******************************************
skipping: [qa-lecture01]

PLAY RECAP ********************************************************************
qa-lecture01               : ok=1    changed=1    unreachable=0    failed=0

これにより、unameでLinuxって返ってきてることはsuccessと判断されているってことね。

failed_when

どうやらfailed_whenは「こういう時はfailedにしてね」って感じのコマンドのようです。
ansible公式サイトより

例としてこんなんが載ってるので、

- name: this command prints FAILED when it fails
  command: /usr/bin/example-command -x -y -z
  register: command_result
  failed_when: "'FAILED' in command_result.stderr"

私の例で言うと

- shell: sakaimo --version
  register: result
  failed_when: "'command not found' in result.stderr"

- debug: msg="debug"

標準エラー(stderr)に「command not found」っていう文字列が含まれていたらfailedとして判定してね、って指定しました。

実行結果

PLAY [app] ********************************************************************

TASK: [sakaimo | shell sakaimo --version] *************************************
failed: [qa-lecture01] => {"changed": true, "cmd": "sakaimo --version", "delta": "0:00:00.139589", "end": "2015-05-12 12:07:03.049756", "failed": true, "failed_when_result": true, "rc": 127, "start": "2015-05-12 12:07:02.910167", "stdout_lines": [], "warnings": []}
stderr: /bin/sh: sakaimo : command not found

FATAL: all hosts have already failed -- aborting

PLAY RECAP ********************************************************************
           to retry, use: --limit @/root/qa-lecture-playbook.retry

qa-lecture01               : ok=0    changed=0    unreachable=0    failed=1

うん、想定通りエラーになりました。そしてエラーになって処理が止まっているので、debugは出力されていません。

では今度は実行結果にerrorrrrrっていう文字列があったらfailedにするようにしてみます。

- shell: sakaimo --version
  register: result
  failed_when: "'errorrrrr'in result.stderr"

- debug: msg="debug"

にした場合、

PLAY [app] ********************************************************************

TASK: [sakaimo | shell sakaimo --version] *************************************
changed: [qa-lecture01]

TASK: [sakaimo | debug msg="debug"] *******************************************
ok: [qa-lecture01] => {
    "msg": "debug"
}

PLAY RECAP ********************************************************************
qa-lecture01               : ok=2    changed=1    unreachable=0    failed=0

となりました。errorrrrrは(リモートサーバーから)出力されていないので  successとみなされ failedではないとみなされ、次の処理に進んでdebugも表示されています。

ではwhen: result|successを追加したらどうでしょうか。

- shell: sakaimo --version
  register: result
  failed_when: "'errorrrrr'in result.stderr"

- debug: msg="debug"
  when: result|success #←ここ
PLAY [app] ********************************************************************

TASK: [sakaimo | shell sakaimo --version] *************************************
changed: [qa-lecture01]

TASK: [sakaimo | debug msg="debug"] *******************************************
skipping: [qa-lecture01]

PLAY RECAP ********************************************************************
qa-lecture01               : ok=1    changed=1    unreachable=0    failed=0

debugがskipされています。つまりresultfailedだったってことですね。

ということは、failed_whenを使って「こういう時はfailedにしてね」という指定はできるけれども、これは「それ以外のときはsuccsessだよ」という指定ではないってことですよねあたりまえかw

ためしに

- shell: sakaimo --version
  register: result
  failed_when: "'errorrrrr'in result.stderr"

- debug: msg="debug"
  when: result|failed #←ここを変えた

にして実行したら

PLAY [app] ********************************************************************

TASK: [sakaimo | shell sakaimo --version] *************************************
changed: [qa-lecture01]

TASK: [sakaimo | debug msg="debug"] *******************************************
ok: [qa-lecture01] => {
    "msg": "debug"
}

PLAY RECAP ********************************************************************
qa-lecture01               : ok=2    changed=1    unreachable=0    failed=0

になりました。

ということは

- shell: sakaimo --version
  register: result
  failed_when: "'errorrrrr'in result.stderr"

- debug: msg="debug"
  when: result|failed #←ここを変えた

において、

  • sakaimo --versionのリモートサーバーでの実行結果は-bash: sakaimo: command not found
  • だからresultにはfailedが入る (when: result|failed がtrue判定されてdebugが出力されているから)
  • なんだけどfailed_when: "'errorrrrr'in result.stderr"でfailedの条件を指定してしまっている
  • だからこの3行全体での処理結果としては「failedじゃない」(successとはいえない)けど、resultfailedなのでdebugは実行される

...あれ、頭がこんがらがってきた。

78
79
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
78
79