12

我对 Ansible 相当陌生,我正在尝试创建一个将文件复制到远程服务器的角色。每次我运行 playbook 时,本地文件可以有不同的名称,但需要远程复制到相同的名称,如下所示:

- name: copy file
  copy:
    src=*.txt
    dest=/path/to/fixedname.txt

Ansible 不允许使用通配符,所以当我编写一个包含主要剧本中任务的简单剧本时,我可以这样做:

- name: find the filename
    connection: local
    shell: "ls -1 files/*.txt"
    register: myfile

- name: copy file
  copy:
    src="files/{{ item }}"
    dest=/path/to/fixedname.txt
  with_items:
   - myfile.stdout_lines

但是,当我将任务移动到角色时,第一个操作不再起作用,因为相对路径是相对于角色的,而剧本在“角色”目录的根目录中执行。我可以将路径添加到角色的文件目录,但是有没有更优雅的方法?

4

2 回答 2

13

看起来您需要访问在本地查找信息的任务,然后将该信息用作复制模块的输入。

有两种方法可以获取本地信息。

  • 使用local_action:. 这是针对 127.0.0.1 运行任务的简写,更多信息可在此处找到。(这是你一直在使用的)

  • 使用lookup. 这是一个专门为在本地获取信息而设计的插件系统。更多信息在这里

在你的情况下,我会选择第二种方法,使用lookup. 你可以像这个例子一样设置它:

vars:
  local_file_name: "{{ lookup('pipe', 'ls -1 files/*.txt') }}"

tasks:
  - name: copy file
    copy: src="{{ local_file_name }}" dest=/path/to/fixedname.txt    

或者,更直接地:

tasks:
  - name: copy file
    copy: src="{{ lookup('pipe', 'ls -1 files/*.txt') }}" dest=/path/to/fixedname.txt    

关于路径

查找插件从任务的上下文中运行(剧本与角色)。这意味着它的行为会根据使用的位置而有所不同。

在上面的设置中,任务直接从剧本运行,所以工作目录将是:

/path/to/project-- 这是你的剧本所在的文件夹。

如果您将任务添加到角色的位置,则工作目录将是:

/path/to/project/roles/role_name/tasks

此外,filepipe插件从角色/文件文件夹中运行(如果存在) :

/path/to/project/roles/role_name/files-- 这意味着你的命令是ls -1 *.txt

警告:

每次访问变量时都会调用该插件。这意味着您不能相信在您的剧本中调试变量,然后依赖该变量在稍后在角色中使用时具有相同的值!

不过,我确实想知道,关于驻留在项目 ansible 文件夹中的文件的用例,但事先不知道谁的名字。这样的文件是从哪里来的?是不是可以在文件的生成和在 Ansible 中使用它之间添加一个层......或者有一个固定的本地路径作为变量?只是好奇 ;)

于 2014-06-16T21:43:37.943 回答
8

只是想提出一个额外的答案......我和你有同样的问题,我在其中构建了一个 ansible 包并将工件(rpms)复制到角色的文件夹中,并且我的 rpms 在文件名中有版本。

当我运行 ansible play 时,我希望它安装所有 rpm,而不管文件名如何。

我通过使用with_fileglobansible中的机制解决了这个问题:

- name: Copy RPMs
  copy: src="{{ item }}" dest="{{ rpm_cache }}"
  with_fileglob: "*.rpm"
  register: rpm_files

- name: Install RPMs
  yum: name={{ item }} state=present
  with_items: "{{ rpm_files.results | map(attribute='dest') | list }}"

我发现它比查找机制更干净一点。

于 2016-08-17T18:33:58.587 回答