I'm trying to generate a script to be copied in an ansible
expect/response block with ssh
to the remote host. I'd like to avoid writing intermediate files.
I have two issues:
command
which messes up multiline bash
scripts, but I can get around it with /bin/bash -c 'my \ multi \ line \ command'
(on actual multiple lines)bash
invocation (see below) - 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
(Note that in this example I'm apparently getting away with using single quotes within single quotes, but other variations all fail as well.)
I have tried to escape the quotes around the first EOF
in different ways, but I always get the warning:
"stdout_lines": ["/bin/bash: line 10: warning: here-document at line 0 delimited by end-of-file (wanted `EOF')", "", "[email protected]'s password: "]
And the contents of myscript.sh
are either not correctly left alone (i.e. all $...
expanded), or contain the last EOF
(since it is not recognized as delimiter and is just reading to the end of the command block, hence the warning.
What is the correct way of handling this?
(Note that I delegate to localhost
because I don't want to rely on python
on the target host, these are minimal systems with only ssh
).
Move the closing EOF left by two spaces. At the moment it does not start at the beginning of its line, so bash won't see it as a delimiter.
From the bash man-page:
Here Documents
This type of redirection instructs the shell to read input from the current source until a line containing only delimiter (with no trailing blanks) is seen. All of the lines read up to that point are then used as the standard input for a command. The format of here-documents is:
<<[-]word here-document delimiter
No parameter expansion, command substitution, arithmetic expansion, or pathname expansion is performed on
word
. If any characters inword
are quoted, thedelimiter
is the result of quote removal onword
, and the lines in the here-document are not expanded. Ifword
is unquoted, all lines of the here-document are subjected to parameter expansion, command substitution, and arithmetic expansion. In the latter case, the character sequence \<newline> is ignored, and \ must be used to quote the characters \, $, and `. If the redirection operator is<<-
, then all leading tab characters are stripped from input lines and the line containingdelimiter
. This allows here-documents within shell scripts to be indented in a natural fashion.
So you'll either need to remove the indentation from the EOF
line or indent everything with TABs instead of spaces. I suggest that the former option is simpler.