Reputation: 3094
I'm attempting to write a script that runs on a remote machine.
As this script is complex, I've broken parts of it down into functions that I then copy into the script using typeset
.
When I run the script, I get the following error:
bash: -c: line 4: syntax error: unexpected end of file
However, there is no unexpected end of file! I ensured all if
s had fi
s, all {
had }
, etc.
I've ensured all indentation uses tabs (and spaces), and ensured new-line characters are consistent.
I've stripped the code down to a minimal example. It seems as though for a function to be valid, it needs to end in a construct such as if
fi
or while
done
.
Here's what isn't working.
func() {
ls ~/
}
ssh -A -T user@machine_ip '
'$(typeset -f func)'
func
'
Line 4 coincides with the end }
of the func
function (counting lines from after ssh -A -T...
as this error is happening on the remote machine).
Yet, if we add a construct to the end of the function, the home directory is printed as expected.
func() {
ls ~/
if [[ 1 ]]; then
echo "Hello"
fi
}
or
func() {
ls ~/
while false; do
echo "Here"
done
}
Output of typeset -f func
is
func ()
{
ls --color=auto ~/;
if [[ -n 1 ]]; then
echo "Hello";
fi
}
I'm running Ubuntu 18.04 LTS, remote machine is running Centos 6.
Upvotes: 0
Views: 61
Reputation: 48
first of all, the way you use quotes make no sense to me.
ssh -A -T user@machine_ip '
'$(typeset -f func)'
func
'
the 2 first ' just echo an empty line. ( the 2nd ' close the 1st. logic ? )
Anyway.
$(typeset -f func)
func
the code above will execute func 2 times. At least, thats how it works for me
....
Upvotes: 0
Reputation: 198294
Because bash plays with whitespace if you let it. Let me explain:
$(typeset -f func)
will evaluate typeset -f func
and insert its output into the current command line. If not quoted, it will also segment into parameters, which will have as a side effect collapsing of all whitespace to a single space. Thus, if typeset -f func
prints (as it does on my system)
func ()
{
/bin/ls --color=auto ~/
}
what you get with $(typeset -f func)
is
func () { /bin/ls --color=auto ~/ }
(Try echo $(typeset -f func)
if you don't believe me :D )
Now, bash is really bashful about accepting smushed-up code. For example, you may know that this is not grammatical:
if true then echo "yes" fi
and this is:
if true; then echo "yes"; fi
In the same way, the function definition's closing parenthesis is picky. Thus, this works:
func () { /bin/ls --color=auto ~/; }
but this doesn't:
func () { /bin/ls --color=auto ~/ }
For some reason, bash is fine with a keyword being just before the parenthesis:
func () { /bin/ls --color=auto ~/; if [[ -n 1 ]]; then echo "Hello"; fi }
func () { /bin/ls --color=auto ~/; while false; do echo "Here"; done }
To combat this... try not sending stuff from command line, which mangles your whitespace, but from redirection:
ssh -A -T user@machine_ip < <(typeset -f func; echo func)
Or, simplest of all, prevent bash
mangling of whitespace using double quotes:
ssh -A -T user@machine_ip "$(typeset -f func)
func"
Upvotes: 1