1

I have a shell script as follows

#!/bin/bash
USER=someuser
HOSTNAMEORIP=somehostname
SCRIPT="/etc/rc.d/netif restart && /etc/rc.d/routing restart"
su -c "ssh -l ${USER} ${HOSTNAMEORIP} ${SCRIPT}" -s /bin/sh someotheruser

If I login to the machine and just run the "/etc/rc.d/netif restart && /etc/rc.d/routing restart" it works. But if i run the entire script above, i get sh: 1: /etc/rc.d/routing: not found as if it's not handling the script part the same. I can even use the above script without a user like this

#!/bin/bash
USER=someuser
HOSTNAMEORIP=somehostname
SCRIPT="/etc/rc.d/netif restart && /etc/rc.d/routing restart"
ssh -l ${USER} ${HOSTNAMEORIP} ${SCRIPT}

And it works but I need to use su -c <command> -s /bin/sh user because another application is calling the script and the user associated is the only one with ssh-key login/no password to the other machine.

How can i make su -c "ssh -l ${USER} ${HOSTNAMEORIP} ${SCRIPT}" -s /bin/sh someotheruser run the script properly in this use case?

3
  • I think it's running /etc/rc.d/routing restart on the calling machine rather than the machine you are sshing to. Try separating SCRIPT into two commands rather than together. Commented Jul 15, 2017 at 16:12
  • same issue with ${SCRIPT1} && ${SCRIPT2} Commented Jul 15, 2017 at 16:26
  • I mean two separate ssh commands: su -c "ssh -l ${USER} ${HOSTNAMEORIP} ${SCRIPT1}" -s /bin/sh someotheruser su -c "ssh -l ${USER} ${HOSTNAMEORIP} ${SCRIPT2}" -s /bin/sh someotheruser Commented Jul 15, 2017 at 16:39

1 Answer 1

5

Let's just work through it. This command:

su -c "ssh -l ${USER} ${HOSTNAMEORIP} ${SCRIPT}" -s /bin/sh someotheruser

Will execute this string as a shell command:

ssh -l someuser somehostname /etc/rc.d/netif restart && /etc/rc.d/routing restart

This is clearly wrong, and will fail with the same error.

To fix it, let's fix the command and work backwards. You should be executing

ssh -l someuser somehostname '/etc/rc.d/netif restart && /etc/rc.d/routing restart'

Therefore, you can update your script like this:

#!/bin/bash
USER=someuser
HOSTNAMEORIP=somehostname
SCRIPT="/etc/rc.d/netif restart && /etc/rc.d/routing restart"
su -c "ssh -l ${USER} ${HOSTNAMEORIP} '${SCRIPT}'" -s /bin/sh someotheruser
#                                     ^---      ^---

Note that this hinges on the fact that $SCRIPT does not contain embedded single quotes. If does or if you don't know, you can use $(printf "%q" "$SCRIPT") instead of '$SCRIPT' in the embedded string to have bash auto-escape it.

Or you can switch to sudo. Since it uses safe and robust execve(2) semantics instead of system(3) semantics, you wouldn't have to nest escaping:

sudo -u someotheruser ssh -l "$USER" "$HOSTNAMEORIP" "$SCRIPT"
Sign up to request clarification or add additional context in comments.

3 Comments

@jtlindsey My sense was that the ssh -t -t would fix the issue by allowing the ssh to allocate a tty. I'll noodle on the problem further.
@Technophobe01 That won't help, since the quoting problem means && /etc/rc.d/routing restart is being parsed and executed on the local computer, not passed to ssh.
Gordon Davisson - Agreed. 'That other guy' provided a nice clean answer and explanation. :-)

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.