【问题标题】:Ansible quoted heredoc in expect/command block not finding delimiter / multiline command in expect commandAnsible 在期望/命令块中引用了 heredoc 在期望命令中找不到分隔符/多行命令
【发布时间】:2020-12-27 06:47:04
【问题描述】:

我正在尝试生成一个脚本,该脚本将在带有sshansible 期望/响应块中复制到远程主机。我想避免编写中间文件。

我有两个问题:

  1. Ansible 似乎在 command 中进行了一些处理,这会弄乱多行 bash 脚本,但我可以使用 /bin/bash -c 'my \ multi \ line \ command' 解决它(在实际多行上)
  2. 我似乎无法在bash 调用中正确 中为heredoc 引用EOF 标记(见下文)
  - 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 的最小系统。

【问题讨论】:

  • 确保EOF 行的缩进只有TAB 字符,而不是空格。
  • 那很快 ;) 不幸的是,这给了:Syntax Error while loading YAML. found a tab character where an indentation space is expected
  • 如果 YAML 不允许使用制表符,则不能使用缩进的 EOF 令牌。

标签: bash ansible escaping heredoc


【解决方案1】:

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

来自 bash 手册页:

这里的文档

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

<<[-]word
        here-document 
delimiter 

不执行参数扩展、命令替换、算术扩展或路径名扩展 在word。如果 word 中的任何字符被引用,则 delimiter 是 在word 上删除引号的结果,以及此处文档中的行 没有展开。如果word 未引用,则此处文档的所有行 受到参数扩展、命令替换和 算术扩展。在后一种情况下,字符序列 \ 被忽略,必须使用 \ 来引用字符 \, $,和`。如果重定向操作符是&lt;&lt;-,那么所有前导制表符 字符从输入行和包含的行中删除 delimiter。这允许 shell 脚本中的 here-documents 以自然的方式缩进。

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

【讨论】:

  • “两个空格缩进”结合双引号(即&lt;&lt;-"EOF")成功了! (单引号被识别为分隔符,但不小心解析了heredoc。)谢谢!
  • 当我们这样做的时候:有没有办法在 command: | 中执行多行而不需要额外的 bash 调用?
  • 我怀疑使用单引号可能会丢失,因为您的整个字符串都在单引号内,但我不能肯定。
  • 你可以将你的shell脚本写在一行上(用;分隔命令),虽然这可能只是意味着你会在命令的开头删除bash并把它in 作为ssh 的参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-07
  • 2015-03-04
  • 1970-01-01
  • 2014-08-11
相关资源
最近更新 更多