Reputation: 33
I'm writing a script that would give me an ability to execute other local bash scripts remotely over SSH without uploading them. Some of my servers have Linux, some FreeBSD with csh as default. So far, I've came to the following:
ssh remote_server 'bash -c '\'"$(cat local_script.sh)"\'' script_parameters'
This allows me to execute local_script.sh on remote_server, supports interactivity (for example, "read" command will work in local_script.sh), and I can transfer positional parameters to the script. The problem is that if a local_script.sh has multiple lines the code above works for remote servers with bash default shell only. On FreeBSD sshd starts csh first to execute "bash -c" command and tries to pass the script code (the result of $(cat local_script.sh)) to it as the first parameter. But because this code is multiline and csh wants the closing quote be on the same line as the opening quote I get the "Unmatched '." error. So csh just can't parse this escaped multiline parameter to pass it to the bash process.
The only solution I can see now is to parse the local_script.sh and automatically rewrite it into a one-liner using ";" delimiters before passing it via SSH. But this requires creating another script and seems to be not so easy. So I'd like to ask if this csh miltiline parsing problem can be resolved somehow?
Upvotes: 3
Views: 1026
Reputation: 19315
What about using standard input /dev/stdin
?
ssh remote_server bash /dev/stdin script_parameters < local_script.sh
Using two different commands and temporary file
bash
ssh remote_server $'tmp=`mktemp tmp.XXXXXX`;cat <<\'HEREDOC_END\' >"$tmp"
'"$(cat local_script.sh)"'
HEREDOC_END
bash "$tmp" script_parameters ;rm "$tmp"'
csh
ssh remote_server 'set tmp=`mktemp tmp.XXXXXX`;cat <<"HEREDOC_END" >"$tmp"
'"$(cat local_script.sh)"'
"HEREDOC_END"
bash "$tmp" script_parameters ;rm "$tmp"'
Upvotes: 1
Reputation: 189357
In this particular case, there is no need to keep the outermost quotes.
ssh remote_server bash -c "\"$(cat local_script.sh)\"" script_parameters
This is not entirely robust; for example, single quotes in local_script.sh
will not quote text verbatim. So the following example
echo 'fnord "$(echo yes)"'
will have the command substitution evaluated remotely even though the string is in single quotes. In the general case, you'd have to replace cat
with, basically, a shell parser which identifies constructs which need escaping.
Upvotes: 0