stdoutとstdout_linesの改行
はじめに
register
を使用したときに保存されるデータの中に、stdout
とstdout_lines
があります。
この2つの改行の扱いについて検証しました。
やったこと
Cisco DevNet SandboxのIOS XE on CSR1000vにshow ntp associations
して、下記を比較しました。
stdout | stdout[0] | stdout_lines | stdout_lines[0] | |
---|---|---|---|---|
debug 出力結果 |
? | ? | ? | ? |
copy 保存結果 |
? | ? | ? | ? |
結論
debug
モジュールの結果を見やすくしたいなら、stdout_lines
を使用するcopy
モジュールで保存するならstdout[0]
を使用する
環境
Ansibleのバージョン
# ansible --version ansible 2.9.7 config file = None configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /usr/local/lib/python3.6/site-packages/ansible executable location = /usr/local/bin/ansible python version = 3.6.8 (default, Apr 2 2020, 13:34:55) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
Playbook
処理概要は下記です。
show ntp associations
の実行結果をregister
するstdout
ロール内で、下記を実行stdout
をdebug
モジュールで出力stdout[0]
をdebug
モジュールで出力stdout
をcopy
モジュールで保存stdout[0]
をcopy
モジュールで保存
stdout_lines
ロール内で、下記を実行stdout_lines
をdebug
モジュールで出力stdout_lines[0]
をdebug
モジュールで出力stdout_lines
をcopy
モジュールで保存stdout_lines[0]
をcopy
モジュールで保存
Playbook構成
# tree . ├── inventory.yml ├── ntp.yml └── roles ├── stdout │ └── tasks │ └── main.yml └── stdout_lines └── tasks └── main.yml
ntp.yml
--- - hosts: csr1000v gather_facts: no tasks: - name: show ntp associations ios_command: commands: - show ntp associations register: res_ntp tags: common - name: import stdout import_role: name: stdout tags: stdout - name: import stdout_lines import_role: name: stdout_lines tags: stdout_lines
stdout
ロール
- block: - name: debug res_ntp as stdout without index debug: var: res_ntp.stdout - name: debug res_ntp as stdout with index debug: var: res_ntp.stdout[0] tags: show - block: - name: save res_ntp as stdout without index copy: content: "{{ res_ntp.stdout }}" dest: ntp_stdout.txt - name: save res_ntp as stdout with index copy: content: "{{ res_ntp.stdout[0] }}" dest: ntp_stdout0.txt tags: save
stdout_lines
ロール
- block: - name: debug res_ntp as stdout_lines without index debug: var: res_ntp.stdout_lines - name: debug res_ntp as stdout_lines with index debug: var: res_ntp.stdout_lines[0] tags: show - block: - name: save res_ntp as stdout_lines without index copy: content: "{{ res_ntp.stdout_lines }}" dest: ntp_stdout_lines.txt - name: save res_ntp as stdout_lines with index copy: content: "{{ res_ntp.stdout_lines[0] }}" dest: ntp_stdout_lines0.txt tags: save
実行結果
stdout
# ansible-playbook -i inventory.yml ntp.yml -t common,stdout PLAY [csr1000v] ***************************************************************************** TASK [show ntp associations] **************************************************************** ok: [csr1000v] TASK [stdout : debug res_ntp as stdout without index] *************************************** ok: [csr1000v] => { "res_ntp.stdout": [ "address ref clock st when poll reach delay offset disp\n ~1.1.1.1 .INIT. 16 - 1024 0 0.000 0.000 15937.\n ~2.2.2.2 .INIT. 16 - 1024 0 0.000 0.000 15937.\n ~3.3.3.3 .INIT. 16 - 1024 0 0.000 0.000 15937.\n * sys.peer, # selected, + candidate, - outlyer, x falseticker, ~ configured" ] } TASK [stdout : debug res_ntp as stdout with index] ****************************************** ok: [csr1000v] => { "res_ntp.stdout[0]": "address ref clock st when poll reach delay offset disp\n ~1.1.1.1 .INIT. 16 - 1024 0 0.000 0.000 15937.\n ~2.2.2.2 .INIT. 16 - 1024 0 0.000 0.000 15937.\n ~3.3.3.3 .INIT. 16 - 1024 0 0.000 0.000 15937.\n * sys.peer, # selected, + candidate, - outlyer, x falseticker, ~ configured" } TASK [stdout : save res_ntp as stdout without index] **************************************** ok: [csr1000v] TASK [stdout : save res_ntp as stdout with index] ******************************************* ok: [csr1000v] PLAY RECAP ********************************************************************************** csr1000v : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# cat -n ntp_stdout.txt 1 ["address ref clock st when poll reach delay offset disp\n ~1.1.1.1 .INIT. 16 - 1024 0 0.000 0.000 15937.\n ~2.2.2.2 .INIT. 16 - 1024 0 0.000 0.000 15937.\n ~3.3.3.3 .INIT. 16 - 1024 0 0.000 0.000 15937.\n * sys.peer, # selected, + candidate, - outlyer, x falseticker, ~ configured"]
# cat -n ntp_stdout0.txt 1 address ref clock st when poll reach delay offset disp 2 ~1.1.1.1 .INIT. 16 - 1024 0 0.000 0.000 15937. 3 ~2.2.2.2 .INIT. 16 - 1024 0 0.000 0.000 15937. 4 ~3.3.3.3 .INIT. 16 - 1024 0 0.000 0.000 15937. 5 * sys.peer, # selected, + candidate, - outlyer, x falseticker, ~ configured
stdout_lines
# ansible-playbook -i inventory.yml ntp.yml -t common,stdout_lines PLAY [csr1000v] ***************************************************************************** TASK [show ntp associations] **************************************************************** ok: [csr1000v] TASK [stdout_lines : debug res_ntp as stdout_lines without index] *************************** ok: [csr1000v] => { "res_ntp.stdout_lines": [ [ "address ref clock st when poll reach delay offset disp", " ~1.1.1.1 .INIT. 16 - 1024 0 0.000 0.000 15937.", " ~2.2.2.2 .INIT. 16 - 1024 0 0.000 0.000 15937.", " ~3.3.3.3 .INIT. 16 - 1024 0 0.000 0.000 15937.", " * sys.peer, # selected, + candidate, - outlyer, x falseticker, ~ configured" ] ] } TASK [stdout_lines : debug res_ntp as stdout_lines with index] ****************************** ok: [csr1000v] => { "res_ntp.stdout_lines[0]": [ "address ref clock st when poll reach delay offset disp", " ~1.1.1.1 .INIT. 16 - 1024 0 0.000 0.000 15937.", " ~2.2.2.2 .INIT. 16 - 1024 0 0.000 0.000 15937.", " ~3.3.3.3 .INIT. 16 - 1024 0 0.000 0.000 15937.", " * sys.peer, # selected, + candidate, - outlyer, x falseticker, ~ configured" ] } TASK [stdout_lines : save res_ntp as stdout_lines without index] **************************** ok: [csr1000v] TASK [stdout_lines : save res_ntp as stdout_lines with index] ******************************* ok: [csr1000v] PLAY RECAP ********************************************************************************** csr1000v : ok=5 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
# cat -n ntp_stdout_lines.txt 1 [["address ref clock st when poll reach delay offset disp", " ~1.1.1.1 .INIT. 16 - 1024 0 0.000 0.000 15937.", " ~2.2.2.2 .INIT. 16 - 1024 0 0.000 0.000 15937.", " ~3.3.3.3 .INIT. 16 - 1024 0 0.000 0.000 15937.", " * sys.peer, # selected, + candidate, - outlyer, x falseticker, ~ configured"]]
# cat -n ntp_stdout_lines0.txt 1 ["address ref clock st when poll reach delay offset disp", " ~1.1.1.1 .INIT. 16 - 1024 0 0.000 0.000 15937.", " ~2.2.2.2 .INIT. 16 - 1024 0 0.000 0.000 15937.", " ~3.3.3.3 .INIT. 16 - 1024 0 0.000 0.000 15937.", " * sys.peer, # selected, + candidate, - outlyer, x falseticker, ~ configured"]
まとめ
表現が正しいか自信がないですが、下記の結果となりました。
stdout | stdout[0] | stdout_lines | stdout_lines[0] | |
---|---|---|---|---|
debug出力結果 | リスト\n が解釈されない |
文字列\nr が解釈されない |
リストのリスト\nr が解釈される |
リスト\nr が解釈される |
copy保存結果 | リスト\nr が解釈されない |
文字列\nr が解釈される |
リストのリスト\nr なし |
リスト\nr なし |
改行コードを含むコマンドの出力結果をregister
で保存した場合、stdout
は生で格納し、stdout_lines
は、改行コードを基準にリストとして分割する動作になります。今回の検証パターンでは、copy
モジュールは改行コードを解釈しますが、リストでなく純粋な文字列であることが前提になります。
したがって、はじめの結論に書いたように、下記の利用方法が適切のようです。
debug
モジュールの結果を見やすくしたいなら、stdout_lines
を使用するcopy
モジュールで保存するならstdout[0]
を使用する
データ構造大事。