はじめに
以前、Ansibleのwin_command
モジュールでコマンドを実行した際、出力結果が文字化けしてしまうということがありました。
その際にansible 2.10.x
のwin_command
モジュール(ansible.windows.win_command
)のoutput_encoding_override
を使用したことで、文字化けが解決しました。
この記事では、Ansibleのwin_command(ansible.windows.win_command)
モジュールのoutput_encoding_override
の使い方について説明します。
※公式ドキュメントはこちらから確認できます
パラメータ(アーギュメント)
output_encoding_override
の前に、win_command(ansible.windows.win_command)
のパラメータについて簡単に説明します。
使うことは少ないかもしれませんが、win_command(ansible.windows.win_command)
にもパラメータは存在します。
パラメータ | 選択肢:デフォルト | 機能 |
---|---|---|
chdir | - | コマンド実行前に移動するディレクトリのパスを指定する。 |
creates | - | 作成するファイルのパスを指定する。 指定したファイルが既に存在する場合、この処理は実行されない。 |
free_form | - | 実際に、この名のパラメータがあるわけではない。 コマンドを指定することが必須となる。 |
output_encoding_override | - | この記事で扱うパラメータ。 2.9以前のバージョンには存在しない。 [System.Text.Encoding]::GetEncodings()の出力に基づく有効な文字コードを指定する(Encoding.GetEncodings Method)。 これにより、エンコーディングされた出力結果を書き換える。 |
removes | - | 削除するファイルのパスを指定する。 指定したファイルが存在しない場合、この処理は実行されない。 |
stdin | - | コマンドの引数を指定する。 ※標準入力 (stdin) で引数を渡す理由 |
動作環境
以下の環境で動作を確認しました。
・コントロールノード:RHEL 8.3
・ターゲットノード:Windows Server 2019
どちらもAWSのAmazon EC2を使用しています。
Ansibleのバージョンは2.10.3
です。
$ ansible --version
ansible 2.10.3
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /root/.pyenv/versions/3.9.0/lib/python3.9/site-packages/ansible
executable location = /root/.pyenv/versions/3.9.0/bin/ansible
python version = 3.9.0 (default, Dec 3 2020, 08:36:30) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
output_encoding_override
の使い方
文字化けしたときの状態
文字化けした際、下記のPlaybookを使用していました。
ターゲットノードであるWindows Serverでコマンドw32tm /query /status
を実行させて、コントロールノードであるRHELに結果を表示するという処理内容になっています。
---
- name: '文字化け'
hosts: windows
gather_facts: no
tasks:
- name: 'コマンド実行'
ansible.windows.win_command: w32tm /query /status
register: qiita
- name: '結果表示'
debug:
msg: "{{ qiita }}"
...
実行すると、次のような結果が表示されます。
# ansible-playbook test.yml
PLAY [文字化け] ********************************************************************
TASK [コマンド実行] ******************************************************************
changed: [10.10.10.10]
TASK [結果表示] ********************************************************************
ok: [10.10.10.10] => {
"msg": {
"changed": true,
"cmd": "w32tm /query /status",
"delta": "0:00:00.078167",
"end": "2021-08-03 12:12:25.005529",
"failed": false,
"rc": 0,
"start": "2021-08-03 12:12:24.927362",
"stderr": "",
"stderr_lines": [],
"stdout": "?[?C???W?P?[?^?[: 0 (?x?????)\n?K?w: 4 (???駱?? - (S)NTP ?????)\n???x: -23 (?e?B?b?N????? 119.209ns)\n???[?g?x??: 0.0006471s\n???[?g???U: 7.7908155s\n?Q?? ID: 0xA9FEA97B (?\\?[?X IP: 123.45.67.89)\n??I??????????: 2021/08/03 0:06:57\n?\\?[?X: 123.45.67.89,0x9 \n?|?[?????O??u: 9 (512s)\n\n",
"stdout_lines": [
"?[?C???W?P?[?^?[: 0 (?x?????)",
"?K?w: 4 (???駱?? - (S)NTP ?????)",
"???x: -23 (?e?B?b?N????? 119.209ns)",
"???[?g?x??: 0.0006471s",
"???[?g???U: 7.7908155s",
"?Q?? ID: xxxxxxxxxx (?\\?[?X IP: 123.45.67.89)",
"??I??????????: 2021/08/03 0:06:57",
"?\\?[?X: 123.45.67.89,0x9 ",
"?|?[?????O??u: 9 (512s)",
""
]
}
}
PLAY RECAP *********************************************************************
10.10.10.10 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
結果が文字化けして表示されています。
こちらにも記載があるのですが、Unicode 以外のエンコーディングの多くは不完全で、多くの文字が "?" に変換されるそうです。
文字化けしない状態
文字化けしないように表示するには、下記のように、output_encoding_override
で文字コードを指定します。
今回はshift_jis
を使用しています。
---
- name: '綺麗に出力'
hosts: windows
gather_facts: no
tasks:
- name: 'コマンド実行'
ansible.windows.win_command: w32tm /query /status
args:
output_encoding_override: shift_jis
register: qiita
- name: '結果表示'
debug:
msg: "{{ qiita }}"
...
実行します。
# ansible-playbook test.yml
PLAY [綺麗に出力] ********************************************************************
TASK [コマンド実行] ******************************************************************
changed: [10.10.10.10]
TASK [結果表示] ********************************************************************
ok: [10.10.10.10] => {
"msg": {
"changed": true,
"cmd": "w32tm /query /status",
"delta": "0:00:00.078159",
"end": "2021-08-03 12:16:22.825437",
"failed": false,
"rc": 0,
"start": "2021-08-03 12:16:22.747277",
"stderr": "",
"stderr_lines": [],
"stdout": "閏インジケーター: 0 (警告なし)\n階層: 4 (二次参照 - (S)NTP で同期)\n精度: -23 (ティックごとに 119.209ns)\nルート遅延: 0.0006471s\nルート分散: 7.7908155s\n参照 ID: 0xA9FEA97B (ソース IP: 123.45.67.89)\n最終正常同期時刻: 2021/08/03 0:15:29\nソース: 123.45.67.89,0x9 \nポーリング間隔: 9 (512s)\n\n",
"stdout_lines": [
"閏インジケーター: 0 (警告なし)",
"階層: 4 (二次参照 - (S)NTP で同期)",
"精度: -23 (ティックごとに 119.209ns)",
"ルート遅延: 0.0006471s",
"ルート分散: 7.7908155s",
"参照 ID: xxxxxxxxxx (ソース IP: 123.45.67.89)",
"最終正常同期時刻: 2021/08/03 0:15:29",
"ソース: 123.45.67.89,0x9 ",
"ポーリング間隔: 9 (512s)",
""
]
}
}
PLAY RECAP *********************************************************************
10.10.10.10 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
文字化けせず、正常に出力されています。
余談ですが、以下のようにすることで、必要な情報のみ表示することもできます。
---
- name: '綺麗に出力'
hosts: windows
gather_facts: no
tasks:
- name: 'コマンド実行'
ansible.windows.win_command: w32tm /query /status
args:
output_encoding_override: shift_jis
register: qiita
- name: '結果表示(最終正常同期時刻)'
debug:
msg: "{{ qiita.stdout_lines | select('match', '最終*') | list }}"
...
# ansible-playbook test.yml
PLAY [綺麗に出力] ********************************************************************
TASK [コマンド実行] ******************************************************************
changed: [10.10.10.10]
TASK [結果表示(最終正常同期時刻)] ********************************************************************
ok: [10.10.10.10] => {
"msg": [
"最終正常同期時刻: 2021/08/03 0:15:29"
]
}
PLAY RECAP *********************************************************************
10.10.10.10 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
あとがき
バージョンが上がることで便利な機能が追加されるのはありがたいです。
今後も便利なものがあれば調べてまとめていきたいです。