首页 > 解决方案 > Ansible 在期望/命令块中引用 heredoc 在期望命令中找不到分隔符/多行命令

问题描述

我正在尝试生成要在ansible期望/响应块中复制ssh到远程主机的脚本。我想避免编写中间文件。

我有两个问题:

  1. Ansible 似乎做了一些处理,command其中弄乱了多行bash脚本,但我可以解决它/bin/bash -c 'my \ multi \ line \ command'(在实际多行上)
  2. 我似乎无法在调用中正确引用heredoc的EOF标记bash下文)
  - name: Generate script on the fly
    expect: 
      command: |
        /bin/bash -c 'ssh -o PubkeyAuthentication=no -p {{ ansible_ssh_port }} {{ ansible_user }}@{{ ansible_host }} "cat - > {{ tgtdir }}/myscript.sh" <<-'EOF' 
          #! /bin/env sh
          a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}; THIS=$(cd "$a"; pwd)
          echo "Script dir == ${THIS}"
          echo "{{ someansiblevar }}"
          EOF
        '
      responses:
        (.*)password: "{{ ansible_ssh_pass }}"
    delegate_to: localhost

(请注意,在这个例子中,我显然在单引号中使用单引号,但其他变体也都失败了。)

我试图以不同的方式逃避第一个引号EOF,但我总是收到警告:

"stdout_lines": ["/bin/bash: line 10: warning: here-document at line 0 delimited by end-of-file (wanted `EOF')", "", "admin@192.168.1.111's password: "]

并且内容myscript.sh要么没有正确地单独存在(即全部$...展开),要么包含最后一个EOF(因为它不被识别为定界符并且只是读取到命令块的末尾,因此发出警告。

处理这个的正确方法是什么?

(请注意,我委托给localhost是因为我不想依赖python目标主机,这些是只有 的最小系统ssh)。

标签: bashansibleescapingheredoc

解决方案


将结束的 EOF 向左移动两个空格。目前它不是从行首开始的,因此 bash 不会将其视为分隔符。

从 bash 手册页:

这里的文件

这种类型的重定向指示 shell 从当前源读取输入,直到看到仅包含分隔符(没有尾随空格)的行。然后将所有读取到该点的行用作命令的标准输入。这里文档的格式是:

<<[-]word
        here-document 
delimiter 

不对 . 执行参数扩展、命令替换、算术扩展或路径名扩展word。如果引用了 in 中的任何字符word,则delimiter是删除 on 引号的结果word,并且 here-document 中的行不展开。如果word未加引号,则此处文档的所有行都经过参数扩展、命令替换和算术扩展。在后一种情况下,字符序列 \<newline> 被忽略,并且必须使用 \ 来引用字符 \、$ 和 `。如果重定向运算符是<<-,则从输入行和包含 delimiter. 这允许 shell 脚本中的 here-documents 以自然的方式缩进。

因此,您要么需要从EOF行中删除缩进,要么使用制表符而不是空格来缩进所有内容。我建议前一种选择更简单。


推荐阅读