Ansible 在expect/command 块中引用了heredoc,在expect 命令中找不到分隔符/多行命令

问题描述 投票:0回答:2

我正在尝试生成一个脚本,并在

ansible
期望/响应块中使用
ssh
复制到远程主机。我想避免编写中间文件。

我有两个问题:

  1. Ansible 似乎在
    command
    中进行了一些处理,这会弄乱多行
    bash
    脚本,但我可以使用
    /bin/bash -c 'my \ multi \ line \ command'
    (在实际的多行上)来绕过它
  2. 我似乎无法在bash调用中正确引用heredoc的EOF标记(见下文)
    
    
  3. - 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')", "", "[email protected]'s password: "]

并且 
myscript.sh

的内容要么没有正确地单独保留(即所有

$...
展开),要么包含最后一个
EOF
(因为它不被识别为分隔符并且只是读取到命令块的末尾,因此发出警告。
正确的处理方法是什么?

(请注意,我委托给

localhost

,因为我不想依赖目标主机上的

python
,这些是只有
ssh
的最小系统)。
    

bash ansible escaping heredoc
2个回答
3
投票

来自 bash 手册页:

这里的文件

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

<<[-]word here-document delimiter

不执行参数扩展、命令替换、算术扩展或路径名扩展
在
word

。如果

word
中的任何字符被引用,则
delimiter
word
上的引号删除结果以及此处文档中的行 没有展开。如果
word
未加引号,则此处文档的所有行 受到参数扩展、命令替换和 算术扩展。在后一种情况下,字符序列 \
 被忽略,并且必须使用 \ 来引用字符 \,
$ 和 `.如果重定向运算符是 
<<-,则所有前导选项卡 字符从输入行和包含的行中剥离
delimiter
。这允许 shell 脚本中的此处文档 以自然的方式缩进。

因此,您需要删除
EOF

行中的缩进,或者使用制表符而不是空格来缩进所有内容。我建议前一种选择更简单。

    


0
投票
cut

sed
命令
关键是要正确处理 EOF。 EOF 缩进的替代方案:

<<-

<tab>EOF

" EOF"

如果你不需要here-doc字符串插值

示例(未测试):

cat - <<-' EOF' | cut -c11- > /tmp/example.sh #! /bin/env sh a="/$0"; a=${a%/*}; a=${a#/}; a=${a:-.}; THIS=$(cd "$a"; pwd) echo "Script dir == ${THIS}" echo "{{ someansiblevar }}" EOF

	
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.