0

How to avoid quoting and escaping needed when passing commands and local variables to ssh with sudo?

Found someone providing a creative way to avoid quoting by using here-documents. It sounded like a great idea, but it did not work for me in bash. Here is the advice I found: Quoting in ssh $host $FOO and ssh $host "sudo su user -c $FOO" type constructs

1 Answer 1

2

Here is a basic bash script example.

# Assign values to variables locally.
myvar1="myvalue1"
myvar2="myvalue2"
# Add your local commands here.

ssh myremotehost "$(
cat <<HEREDOC_EXPORT_VARIABLES
export myvar1="$myvar1"
export myvar2="$myvar2"
HEREDOC_EXPORT_VARIABLES

cat <<'HEREDOC_SUDO'
sudo -Eu root /bin/bash <<'HEREDOC_COMMANDS'

# Optionally display your variables.
echo "myvar1: $myvar1"
echo "myvar2: $myvar2"
# Add your remote commands here.

HEREDOC_COMMANDS
HEREDOC_SUDO
)" | tee logfile.log

Explanation of different parts.

Variables assigned values locally (before executing commands on remote machine):

myvar1="myvalue1"
myvar2="myvalue2"

"$( ... )" allow grouping multiple commands together and allow using double quotes within this block.

Export here-document block, which is not in single quotes, allows using local variables in the block:

cat <<HEREDOC_EXPORT_VARIABLES
...
...
HEREDOC_EXPORT_VARIABLES

Exporting of local variables to be available for remote commands.

export myvar1="$myvar1"
export myvar2="$myvar2"

Outer here-document block, which is in single quotes, to echo out sudo command and remove the necessity of escaping of remote variables for inner here-document (potentially may be replaced by echo without the line feed):

cat <<'HEREDOC_SUDO'
...
...
HEREDOC_SUDO

Inner here-document block, which is in single quotes, to remove the necessity of escaping of remote variables.

sudo -Eu root /bin/bash <<'HEREDOC_COMMANDS'
...
...
HEREDOC_COMMANDS

-E option in sudo allows preserving the environment variables, which were exported earlier.

tee logfile.log allows echoing output to terminal and to a log file at the same time.

As a bonus, you could replace ssh myremotehost "$( line with echo "$( and you will get an output of what your remotely executed part will look like for debugging purposes.

Tip: You may need to escape a non-paired single or double quote within "$( ... )" block, even if you use it in a comment.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .