我如何在任务文件内写变量

我有这个 播放

---
- hosts: localhost
    

tasks:
- include: apache.yml

我的 Apache.yml文件如下:

vars:
url: http://example.com/apache
    

- name: Download apache
shell: wget {{ url }}

这是给我一个错误。

如果我删除 vars,那么它的工作。但是,我希望将变量保留在包含的任务文件中,这样就可以将不同任务的不同变量分开。

174289 次浏览

Variable definitions are meant to be used in tasks. But if you want to include them in tasks probably use the register directive. Like this:

- name: Define variable in task.
shell: echo "http://www.my.url.com"
register: url


- name: Download apache
shell: wget \{\{ item }}
with_items: url.stdout

You can also look at roles as a way of separating tasks depending on the different roles roles. This way you can have separate variables for each of one of your roles. For example you may have a url variable for apache1 and a separate url variable for the role apache2.

NOTE: Using set_fact as described below sets a fact/variable onto the remote servers that the task is running against. This fact/variable will then persist across subsequent tasks for the entire duration of your playbook.

Also, these facts are immutable (for the duration of the playbook), and cannot be changed once set.


ORIGINAL ANSWER

Use set_fact before your task to set facts which seem interchangeable with variables:

- name: Set Apache URL
set_fact:
apache_url: 'http://example.com/apache'


- name: Download Apache
shell: wget \{\{ apache_url }}

See http://docs.ansible.com/set_fact_module.html for the official word.

Whenever you have a module followed by a variable on the same line in ansible the parser will treat the reference variable as the beginning of an in-line dictionary. For example:

- name: some example
command: \{\{ myapp }} -a foo

The default here is to parse the first part of \{\{ myapp }} -a foo as a dictionary instead of a string and you will get an error.

So you must quote the argument like so:

- name: some example
command: "\{\{ myapp }} -a foo"

Just move the variable definition inside inside your task:

- name: Download apache
shell: wget \{\{ url }}
vars:
url: http://example.com/apache

In Your example, apache.yml is tasklist, but not playbook

In depends on desired architecture, You can do one of:

  1. Convert apache.yml to role. Then define tasks in roles/apache/tasks/mail.yml and variables in roles/apache/defaults/mail.yml (vars in defaults can be overriden when role applied)

  2. Set vars in play.yml playbook

play.yml

---
- hosts: 127.0.0.1
connection: local
sudo: false


vars:
url: czxcxz


tasks:
- include: apache.yml

apache.yml

- name: Download apache
shell: wget \{\{url}}

If you need to have local variables that only persist through specific task, you can do this:

- name: My Task
vars:
my_var: 123

This can be useful, when you want to have more reusable roles, where it expects some generic variables (arguments). For example:

my_debug_role/main.yml:

- name: Output me
ansible.builtin.debug:
msg: "Your output was: \{\{ my_msg }}"

Then in your playbook, you can reuse it with more specific variable, like:

my_playbook.yml:

- name: Output my custom log
include_role:
name: my_debug_role
vars:
my_msg: "\{\{ some_custom_specific_variable }}"