我正在尝试生成一个脚本,并在
ansible
期望/响应块中使用 ssh
复制到远程主机。我想避免编写中间文件。
我有两个问题:
command
中进行了一些处理,这会弄乱多行 bash
脚本,但我可以使用 /bin/bash -c 'my \ multi \ line \ command'
(在实际的多行上)来绕过它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')", "", "[email protected]'s password: "]
并且
myscript.sh
的内容要么没有正确地单独保留(即所有
$...
展开),要么包含最后一个 EOF
(因为它不被识别为分隔符并且只是读取到命令块的末尾,因此发出警告。正确的处理方法是什么?
(请注意,我委托给
localhost
,因为我不想依赖目标主机上的
python
,这些是只有ssh
的最小系统)。来自 bash 手册页:
这里的文件
这种类型的重定向指示 shell 从 当前源直到仅包含定界符的行(没有 看到尾随空白)。到该点为止读取的所有行都是 然后用作命令的标准输入。格式为 这里的文档是:
<<[-]word here-document delimiter
不执行参数扩展、命令替换、算术扩展或路径名扩展 在word
。如果
中的任何字符被引用,则word
是delimiter
上的引号删除结果以及此处文档中的行 没有展开。如果word
未加引号,则此处文档的所有行 受到参数扩展、命令替换和 算术扩展。在后一种情况下,字符序列 \word
被忽略,并且必须使用 \ 来引用字符 \, $ 和 `.如果重定向运算符是<<-
,则所有前导选项卡 字符从输入行和包含的行中剥离 。这允许 shell 脚本中的此处文档 以自然的方式缩进。 因此,您需要删除delimiter
EOF
行中的缩进,或者使用制表符而不是空格来缩进所有内容。我建议前一种选择更简单。
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