Ansible lineinfile未将最后一行复制到服务器

Ansible lineinfile未将最后一行复制到服务器,ansible,ansible-vault,Ansible,Ansible Vault,我正在尝试将一个机密Python设置文件从设置服务器复制到生产环境。因为设置包含密码,所以我使用Ansible Vault 我的剧本是这样的: --- - hosts: production tasks: - include_vars: settings.yml - name: Set properties lineinfile: dest: ~/temp/deploy regexp: "{{ item.split('=')[0] }}\\s*="

我正在尝试将一个机密Python设置文件从设置服务器复制到生产环境。因为设置包含密码,所以我使用Ansible Vault

我的剧本是这样的:

---
- hosts: production
  tasks:
  - include_vars: settings.yml
  - name: Set properties
    lineinfile:
      dest: ~/temp/deploy
      regexp: "{{ item.split('=')[0] }}\\s*="
      line: "{{ item }}"
    with_lines: echo "{{ config }}"
config:  |
  ASD='DEF'
  PROGRAM='PROG'
  PASSWORD='MAGNUS123'
  TEMP='TEST'
我的settings.yml如下所示:

---
- hosts: production
  tasks:
  - include_vars: settings.yml
  - name: Set properties
    lineinfile:
      dest: ~/temp/deploy
      regexp: "{{ item.split('=')[0] }}\\s*="
      line: "{{ item }}"
    with_lines: echo "{{ config }}"
config:  |
  ASD='DEF'
  PROGRAM='PROG'
  PASSWORD='MAGNUS123'
  TEMP='TEST'
但是,当我运行playbook时,我会得到以下文件:

ASD='DEF'
PROGRAM='PROG'
PASSWORD='MAGNUS123'
即使Ansible声称最后一行也是复制的:

changed: [ssh.pythonanywhere.com] => (item=ASD='DEF' )
changed: [ssh.pythonanywhere.com] => (item=PROGRAM='PROG')
changed: [ssh.pythonanywhere.com] => (item=PASSWORD='MAGNUS123')
changed: [ssh.pythonanywhere.com] => (item=TEMP='TEST')
changed: [ssh.pythonanywhere.com] => (item=)
我做错了什么导致了这一切

可翻译版本:

ansible --version
ansible 2.4.1.0
  config file = None
  ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.6.2 (default, Jul 17 2017, 16:44:45) [GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.42)]

你正在做一些完全不必要的事情(跳到底部),但是让我们试试看

我做错了什么导致了这一切

如果运行以下命令:

- shell: echo "{{ config }}" | hexdump
  register: echo

- debug:
    var: echo.stdout
您将看到输出以以下内容结束:

54 45 4d 50 3d 27 54 45 53 54 27 0a 0a
它是
TEMP='TEST'
,后跟两个换行符。当在
和_行
循环中使用时,这将导致两次迭代——最后一次将空值传递给

现在,想想当
item
为空时,参数会发生什么变化:

regexp
变为
\\s*=
为空

换句话说,您指示Ansible将包含
=
的某行替换为空行

如果起点为空文件,Ansible将执行以下操作:

- shell: echo "{{ config }}" | hexdump
  register: echo

- debug:
    var: echo.stdout
  • 添加
    ASD='DEF'
  • 添加
    PROGRAM='PROG'
  • 添加
    PASSWORD='MAGNUS123'
  • 添加
    TEMP='TEST'
  • 用空行替换
    =
    行(事实上,它恰好是最后一行)
  • 这就是你得到的结果:三行和一个空的


    您也可以通过使用
    debug
    模块来显示传递给
    lineinfle
    参数的
    {{item.split('=')[0]}\\s*='
    {item}
    的值,从而得出相同的结论


    echo
    具有
    -n
    参数(“不要打印尾随的换行符”),但由于我目前无法理解的原因,它不会更改结果(请使用
    hextump
    进行检查)

    但是,如果您将
    echo
    替换为
    printf
    ——则悬挂的
    0x0a
    不在那里,您将得到预期的结果(使用
    hextdump
    进行检查)


    所有这些,除了是一个很好的难题之外,还是反对在Ansible中使用
    linefile
    module的另一个论据


    使用(您可以使用Ansible Vault保护整个文件-请参见
    decrypt
    参数)或(您可以使用公共模板并将变量值存储在受Vault保护的表单中)。定义所需状态,不要依赖当前状态。句号。

    我很好奇:这是你自己发明的还是在什么地方发现的?是我自己发明的,如果有人有一个类似于“放弃这个并使用这个”的解决方案,我会非常清楚这需要一个问题的定义来解决。我在服务器上有一个用Ansible Vault加密的python设置文件。我想在生产环境中更新设置文件,这样,如果设置存在,它会被更新,如果不存在,它会被附加到文件中。为什么不使用模板呢?感谢您告诉我哪里出了问题(工作正常),以及我应该使用什么来代替