0

I am trying to create a SSH Bash wrapper function that will allow me to execute commands remotely. The goal is to have a function name and parameters that are passed to the function without worry of how to escape quoting. The secondary goal (although not as important) is to capture the result of the executed command.

I have tried various methods but none of them seem to work within a function.

Here are two different methods I feel I have come the closest to the desired result with:

#!/bin/bash
s="srvr01"
ss="srvr02"

# Run commands on primary
function ssh1() {
  printf -v var "%s" "$*"
  ssh root@$s <<END
  x() {
    $*
  }
  x "$var"
END
}

# Run commands using secondary method
function ssh2() {
  printf -v var_str "%s" "$*"
  ssh -T -p 22 root@$ss $var_str
}

sshb() {
  ssh1 $*
  ssh2 $*
}

ssh1 echo 'net.ipv4.ip_nonlocal_bind=1' >> /etc/sysctl.conf
ssh2 echo 'net.ipv4.ip_nonlocal_bind=1' >> /etc/sysctl.conf

By passing the function to ssh and then calling it I would've expected the commands to be executed in a safely escaped manner instead of getting:
line 27: /etc/sysctl.conf: Permission denied
line 28: /etc/sysctl.conf: Permission denied

2
  • 1
    You always have to worry about quoting; you can't hide it. Commented Jun 21, 2019 at 1:10
  • 2
    The shell treats >> as a redirection operator before it even tries to determine what the arguments to ssh1 or ssh2 are; you must quote it. Commented Jun 21, 2019 at 1:11

1 Answer 1

1

You need to quote the output redirection operators, otherwise they'll be processed by your local shell rather than being passed as parameters to the function.

ssh1 echo 'net.ipv4.ip_nonlocal_bind=1' '>>' /etc/sysctl.conf
ssh2 echo 'net.ipv4.ip_nonlocal_bind=1' '>>' /etc/sysctl.conf

You also need to use eval in the x() function, because redirection operators aren't processed after expanding variables. And you need to escape the $ in variables that should be expanded on the remote system.

function ssh1() {
  printf -v var "%s" "$*"
  ssh root@$s <<END
  x() {
    eval "\$1"
  }
  x "$var"
END
}

I'm not sure what the point of that printf is, you can just do var="$*" to get the same result. You don't even need the var variable, just use x "$*" Actually, I think I would write that as:

function ssh1() {
    ssh root@$s <<END
$*
END
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you for your answer. I had to modify the ssh root@$s <<END to be ssh root@$s 'bash -s ' <<END so I could avoid a Pseudo-terminal will not be allocated because stdin is not a terminal. error. Thanks for the quick answer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.