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

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.