如何使用 Ansible 读取上一个任务中使用 shell 模块设置的环境变量
How to read environment variable set with shell module in previous task with Ansible
编辑: 我要设置的env变量SYSTEM_VERSION
无法在任务执行前设置。它是在任务期间创建的(例如通过读取仅在剧本执行期间更新的文件)
我有多项任务,其中一项设置了一个环境变量,例如:
- name: Set current version
shell: export SYSTEM_VERSION=$(cat system_version.txt)
register: version_result
然后我希望读取同一主机的环境变量,例如:
- name: Get the version name
command: echo $SYSTEM_VERSION
register: get_version_result
- name: Print variable
debug:
msg: "The operating system is {{ get_version_result.stdout }}"
但这总是return一个空结果。为什么?即使这不是正确的方法,我如何才能读取我在一个任务中设置的变量 shell 稍后在同一主机的另一个任务中?
问:"通过读取在 playbook 执行期间更新的文件来设置环境变量 SYSTEM_VERSION。"
A:您可以在剧本、角色、街区或任务中设置环境。参见 Playbook Keywords。如果您必须在剧本执行期间读取该值,请将环境设置为一个块。例如,剧本
- hosts: test_11
gather_facts: false
tasks:
- file:
state: directory
path: system-versions
- shell: uname -sr > system_version.txt
- fetch:
src: system_version.txt
dest: system-versions
- block:
- command: 'echo $SYSTEM_VERSION'
register: result
- debug:
var: result.stdout
environment:
SYSTEM_VERSION: "{{ lookup('file', system_version_path) }}"
vars:
system_version_path: "system-versions/{{ inventory_hostname}}/system_version.txt"
创建字典 system-versions,其中将存储文件。下一个任务在远程主机
上创建文件system_version.txt
shell> ssh admin@test_11 cat system_version.txt
FreeBSD 13.0-RELEASE
下一个任务取文件存入目录system-versions/test_11
shell> cat system-versions/test_11/system_version.txt
FreeBSD 13.0-RELEASE
块然后在控制器读取这个文件并为块中的任务设置环境
TASK [debug] *********************************************
ok: [test_11] =>
result.stdout: FreeBSD 13.0-RELEASE
下一个选项是在第一次播放中获取文件并在第二次播放中使用它们。例如,给定远程主机上的文件
shell> ssh admin@test_11 cat system_version.txt
System A
shell> ssh admin@test_12 cat system_version.txt
System B
剧本
- hosts: test_11,test_12
gather_facts: false
tasks:
- file:
state: directory
path: system-versions
run_once: true
- fetch:
src: system_version.txt
dest: system-versions
- hosts: test_11,test_12
gather_facts: false
vars:
system_version_path: "system-versions/{{ inventory_hostname}}/system_version.txt"
environment:
SYSTEM_VERSION: "{{ lookup('file', system_version_path) }}"
tasks:
- command: 'echo $SYSTEM_VERSION'
register: result
- debug:
var: result.stdout
在第一个播放中获取文件
shell> cat system-versions/test_11/system_version.txt
System A
shell> cat system-versions/test_12/system_version.txt
System B
并在第二个播放中设置环境。给出(删节)
TASK [debug] ***********************************************
ok: [test_11] =>
result.stdout: System A
ok: [test_12] =>
result.stdout: System B
备注
- 请参阅 Ansible architecture 了解 Ansible 的工作原理。引用:
Ansible works by connecting to your nodes and pushing out scripts called “Ansible modules” to them. Most modules accept parameters that describe the desired state of the system. Ansible then executes these modules (over SSH by default), and removes them when finished. ...
- 你可以看看一个模块在什么环境下工作。例如,给定库存
shell> cat hosts
[test]
test_11
[test:vars]
ansible_connection=ssh
ansible_user=admin
剧本
shell> cat playbook.yml
- hosts: test_11
gather_facts: false
tasks:
- command: '/bin/sh -c set'
register: result
- debug:
var: result.stdout
启用连接调试时给出 (-vvvv)
shell> ansible-playbook -i hosts playbook.yml -vvvv
...
<test_11> ESTABLISH SSH CONNECTION FOR USER: admin
<test_11> SSH: EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="admin"' -o ConnectTimeout=10 -o ControlPath=/export/home/vlado.config/.ansible/cp/9d96571b11 -tt test_11 '/bin/sh -c '"'"'/usr/local/bin/python3.8 /home/admin/.ansible/tmp/ansible-tmp-1649217448.1346543-1545740-216049530990371/AnsiballZ_command.py && sleep 0'"'"''
<test_11> (0, b'\r\n{"changed": true, "stdout": "BLOCKSIZE=K\nHOME=/home/admin\nIFS=$' \t\n'\nLANG=C.UTF-8\nLOGNAME=admin\nMAIL=/var/mail/admin\nMM_CHARSET=UTF-8\nOPTIND=1\nPATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/admin/bin\nPPID=26056\nPS1='$ '\nPS2='> '\nPS4='+ '\nPWD=/home/admin\nSHELL=/bin/sh\nSSH_CLIENT='10.1.0.184 50874 22'\nSSH_CONNECTION='10.1.0.184 50874 10.1.0.61 22'\nSSH_TTY=/dev/pts/0\nTERM=xterm-256color\nUSER=admin", "stderr": "", "rc": 0, "cmd": ["/bin/sh", "-c", "set"], "start": "2022-04-06 03:57:29.500158", "end": "2022-04-06 03:57:29.516366", "delta": "0:00:00.016208", "msg": "", "invocation": {"module_args": {"_raw_params": "/bin/sh -c set", "_uses_shell": false, "warn": false, "stdin_add_newline": true, "strip_empty_ends": true, "argv": null, "chdir": null, "executable": null, "creates": null, "removes": null, "stdin": null}}}\r\n', b'OpenSSH_8.2p1 Ubuntu-4ubuntu0.2, OpenSSL 1.1.1f 31 Mar 2020\r\ndebug1: Reading configuration data /home/vlado/.ssh/config\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/ssh_config line 2: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug2: mux_client_hello_exchange: master version 4\r\ndebug3: mux_client_forwards: request forwardings: 0 local, 0 remote\r\ndebug3: mux_client_request_session: entering\r\ndebug3: mux_client_request_alive: entering\r\ndebug3: mux_client_request_alive: done pid = 1545744\r\ndebug3: mux_client_request_session: session request sent\r\ndebug3: mux_client_read_packet: read header failed: Broken pipe\r\ndebug2: Received exit status from master 0\r\nShared connection to test_11 closed.\r\n')
result.stdout: |-
BLOCKSIZE=K
HOME=/home/admin
IFS=$' \t
'
LANG=C.UTF-8
LOGNAME=admin
MAIL=/var/mail/admin
MM_CHARSET=UTF-8
OPTIND=1
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/admin/bin
PPID=26008
PS1='$ '
PS2='> '
PS4='+ '
PWD=/home/admin
SHELL=/bin/sh
SSH_CLIENT='10.1.0.184 50834 22'
SSH_CONNECTION='10.1.0.184 50834 10.1.0.61 22'
SSH_TTY=/dev/pts/0
TERM=xterm-256color
USER=admin
- 可选地,您可以让 Ansible 收集 facts
shell> cat playbook.yml
- hosts: test_11
gather_facts: true
tasks:
- debug:
var: ansible_env
给予
ansible_env:
BLOCKSIZE: K
HOME: /home/admin
LANG: C.UTF-8
LOGNAME: admin
MAIL: /var/mail/admin
MM_CHARSET: UTF-8
PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/admin/bin
PWD: /home/admin
SHELL: /bin/sh
SSH_CLIENT: 10.1.0.184 51008 22
SSH_CONNECTION: 10.1.0.184 51008 10.1.0.61 22
SSH_TTY: /dev/pts/0
TERM: xterm-256color
USER: admin
- 您可以在 *nix the module command and the ssh connection uses SHELL=/bin/sh. If you want to change it use the parameter executable of the module shell.
中看到
例如剧本
- hosts: test_11
gather_facts: false
tasks:
- shell: 'echo $SHELL'
register: result
- debug:
var: result.stdout
- shell: 'export MYVAR1=test; echo $MYVAR1'
register: result
- debug:
var: result.stdout
- shell: 'echo $MYVAR1'
register: result
- debug:
var: result.stdout
给予
TASK [shell] ********************************************************
changed: [test_11]
TASK [debug] ********************************************************
ok: [test_11] =>
result.stdout: /bin/sh
TASK [shell] ********************************************************
changed: [test_11]
TASK [debug] ********************************************************
ok: [test_11] =>
result.stdout: test
TASK [debug] ********************************************************
changed: [test_11]
TASK [debug] ********************************************************
ok: [test_11] =>
result.stdout: ''
- 可以看到没有持久化设置环境变量。每个模块都会创建一个新的登录名。解决方案是使用关键字 environment。例如
- hosts: test_11
gather_facts: false
environment:
MYVAR1: test
tasks:
- shell: 'echo $MYVAR1'
register: result
- debug:
var: result.stdout
按预期给予
result.stdout: test
编辑: 我要设置的env变量SYSTEM_VERSION
无法在任务执行前设置。它是在任务期间创建的(例如通过读取仅在剧本执行期间更新的文件)
我有多项任务,其中一项设置了一个环境变量,例如:
- name: Set current version
shell: export SYSTEM_VERSION=$(cat system_version.txt)
register: version_result
然后我希望读取同一主机的环境变量,例如:
- name: Get the version name
command: echo $SYSTEM_VERSION
register: get_version_result
- name: Print variable
debug:
msg: "The operating system is {{ get_version_result.stdout }}"
但这总是return一个空结果。为什么?即使这不是正确的方法,我如何才能读取我在一个任务中设置的变量 shell 稍后在同一主机的另一个任务中?
问:"通过读取在 playbook 执行期间更新的文件来设置环境变量 SYSTEM_VERSION。"
A:您可以在剧本、角色、街区或任务中设置环境。参见 Playbook Keywords。如果您必须在剧本执行期间读取该值,请将环境设置为一个块。例如,剧本
- hosts: test_11
gather_facts: false
tasks:
- file:
state: directory
path: system-versions
- shell: uname -sr > system_version.txt
- fetch:
src: system_version.txt
dest: system-versions
- block:
- command: 'echo $SYSTEM_VERSION'
register: result
- debug:
var: result.stdout
environment:
SYSTEM_VERSION: "{{ lookup('file', system_version_path) }}"
vars:
system_version_path: "system-versions/{{ inventory_hostname}}/system_version.txt"
创建字典 system-versions,其中将存储文件。下一个任务在远程主机
上创建文件system_version.txtshell> ssh admin@test_11 cat system_version.txt
FreeBSD 13.0-RELEASE
下一个任务取文件存入目录system-versions/test_11
shell> cat system-versions/test_11/system_version.txt
FreeBSD 13.0-RELEASE
块然后在控制器读取这个文件并为块中的任务设置环境
TASK [debug] *********************************************
ok: [test_11] =>
result.stdout: FreeBSD 13.0-RELEASE
下一个选项是在第一次播放中获取文件并在第二次播放中使用它们。例如,给定远程主机上的文件
shell> ssh admin@test_11 cat system_version.txt
System A
shell> ssh admin@test_12 cat system_version.txt
System B
剧本
- hosts: test_11,test_12
gather_facts: false
tasks:
- file:
state: directory
path: system-versions
run_once: true
- fetch:
src: system_version.txt
dest: system-versions
- hosts: test_11,test_12
gather_facts: false
vars:
system_version_path: "system-versions/{{ inventory_hostname}}/system_version.txt"
environment:
SYSTEM_VERSION: "{{ lookup('file', system_version_path) }}"
tasks:
- command: 'echo $SYSTEM_VERSION'
register: result
- debug:
var: result.stdout
在第一个播放中获取文件
shell> cat system-versions/test_11/system_version.txt
System A
shell> cat system-versions/test_12/system_version.txt
System B
并在第二个播放中设置环境。给出(删节)
TASK [debug] ***********************************************
ok: [test_11] =>
result.stdout: System A
ok: [test_12] =>
result.stdout: System B
备注
- 请参阅 Ansible architecture 了解 Ansible 的工作原理。引用:
Ansible works by connecting to your nodes and pushing out scripts called “Ansible modules” to them. Most modules accept parameters that describe the desired state of the system. Ansible then executes these modules (over SSH by default), and removes them when finished. ...
- 你可以看看一个模块在什么环境下工作。例如,给定库存
shell> cat hosts
[test]
test_11
[test:vars]
ansible_connection=ssh
ansible_user=admin
剧本
shell> cat playbook.yml
- hosts: test_11
gather_facts: false
tasks:
- command: '/bin/sh -c set'
register: result
- debug:
var: result.stdout
启用连接调试时给出 (-vvvv)
shell> ansible-playbook -i hosts playbook.yml -vvvv
... <test_11> ESTABLISH SSH CONNECTION FOR USER: admin <test_11> SSH: EXEC ssh -vvv -C -o ControlMaster=auto -o ControlPersist=60s -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o 'User="admin"' -o ConnectTimeout=10 -o ControlPath=/export/home/vlado.config/.ansible/cp/9d96571b11 -tt test_11 '/bin/sh -c '"'"'/usr/local/bin/python3.8 /home/admin/.ansible/tmp/ansible-tmp-1649217448.1346543-1545740-216049530990371/AnsiballZ_command.py && sleep 0'"'"'' <test_11> (0, b'\r\n{"changed": true, "stdout": "BLOCKSIZE=K\nHOME=/home/admin\nIFS=$' \t\n'\nLANG=C.UTF-8\nLOGNAME=admin\nMAIL=/var/mail/admin\nMM_CHARSET=UTF-8\nOPTIND=1\nPATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/admin/bin\nPPID=26056\nPS1='$ '\nPS2='> '\nPS4='+ '\nPWD=/home/admin\nSHELL=/bin/sh\nSSH_CLIENT='10.1.0.184 50874 22'\nSSH_CONNECTION='10.1.0.184 50874 10.1.0.61 22'\nSSH_TTY=/dev/pts/0\nTERM=xterm-256color\nUSER=admin", "stderr": "", "rc": 0, "cmd": ["/bin/sh", "-c", "set"], "start": "2022-04-06 03:57:29.500158", "end": "2022-04-06 03:57:29.516366", "delta": "0:00:00.016208", "msg": "", "invocation": {"module_args": {"_raw_params": "/bin/sh -c set", "_uses_shell": false, "warn": false, "stdin_add_newline": true, "strip_empty_ends": true, "argv": null, "chdir": null, "executable": null, "creates": null, "removes": null, "stdin": null}}}\r\n', b'OpenSSH_8.2p1 Ubuntu-4ubuntu0.2, OpenSSL 1.1.1f 31 Mar 2020\r\ndebug1: Reading configuration data /home/vlado/.ssh/config\r\ndebug1: Reading configuration data /etc/ssh/ssh_config\r\ndebug1: /etc/ssh/ssh_config line 2: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug2: mux_client_hello_exchange: master version 4\r\ndebug3: mux_client_forwards: request forwardings: 0 local, 0 remote\r\ndebug3: mux_client_request_session: entering\r\ndebug3: mux_client_request_alive: entering\r\ndebug3: mux_client_request_alive: done pid = 1545744\r\ndebug3: mux_client_request_session: session request sent\r\ndebug3: mux_client_read_packet: read header failed: Broken pipe\r\ndebug2: Received exit status from master 0\r\nShared connection to test_11 closed.\r\n')
result.stdout: |-
BLOCKSIZE=K
HOME=/home/admin
IFS=$' \t
'
LANG=C.UTF-8
LOGNAME=admin
MAIL=/var/mail/admin
MM_CHARSET=UTF-8
OPTIND=1
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/admin/bin
PPID=26008
PS1='$ '
PS2='> '
PS4='+ '
PWD=/home/admin
SHELL=/bin/sh
SSH_CLIENT='10.1.0.184 50834 22'
SSH_CONNECTION='10.1.0.184 50834 10.1.0.61 22'
SSH_TTY=/dev/pts/0
TERM=xterm-256color
USER=admin
- 可选地,您可以让 Ansible 收集 facts
shell> cat playbook.yml
- hosts: test_11
gather_facts: true
tasks:
- debug:
var: ansible_env
给予
ansible_env:
BLOCKSIZE: K
HOME: /home/admin
LANG: C.UTF-8
LOGNAME: admin
MAIL: /var/mail/admin
MM_CHARSET: UTF-8
PATH: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/home/admin/bin
PWD: /home/admin
SHELL: /bin/sh
SSH_CLIENT: 10.1.0.184 51008 22
SSH_CONNECTION: 10.1.0.184 51008 10.1.0.61 22
SSH_TTY: /dev/pts/0
TERM: xterm-256color
USER: admin
- 您可以在 *nix the module command and the ssh connection uses SHELL=/bin/sh. If you want to change it use the parameter executable of the module shell. 中看到
例如剧本
- hosts: test_11
gather_facts: false
tasks:
- shell: 'echo $SHELL'
register: result
- debug:
var: result.stdout
- shell: 'export MYVAR1=test; echo $MYVAR1'
register: result
- debug:
var: result.stdout
- shell: 'echo $MYVAR1'
register: result
- debug:
var: result.stdout
给予
TASK [shell] ********************************************************
changed: [test_11]
TASK [debug] ********************************************************
ok: [test_11] =>
result.stdout: /bin/sh
TASK [shell] ********************************************************
changed: [test_11]
TASK [debug] ********************************************************
ok: [test_11] =>
result.stdout: test
TASK [debug] ********************************************************
changed: [test_11]
TASK [debug] ********************************************************
ok: [test_11] =>
result.stdout: ''
- 可以看到没有持久化设置环境变量。每个模块都会创建一个新的登录名。解决方案是使用关键字 environment。例如
- hosts: test_11
gather_facts: false
environment:
MYVAR1: test
tasks:
- shell: 'echo $MYVAR1'
register: result
- debug:
var: result.stdout
按预期给予
result.stdout: test