Search code examples
bashfunctionsshsudo

Bash: Running a function as sudo on remote host?


I have the following example script, to run commands on a remote host.

The script accepts the remote host's password from user input which we can use to login as that user and I expect also pass to sudo.

The problem is, I can't seem to get the runOnRemoteHostAsRoot function inside the second function to run using sudo, which I need.

How do I get this to work?

Platform at both ends is Ubuntu 18 or 20.

#!/bin/bash

read SSHPASS
export SSHPASS

runOnRemoteHost() {
    # ...
    whoami
    # ...
}
# ...
sshpass -e ssh -o PasswordAuthentication=yes "user@remotehost" "$(declare -f runOnRemoteHost); runOnRemoteHost" 2>&1
# ...


runOnRemoteHostAsRoot() {
    # ...
    whoami
    # ...
}
# ...
echo "${SSHPASS}" | sshpass -e ssh -o PasswordAuthentication=yes "user@remotehost" "$(declare -f runOnRemoteHostAsRoot); sudo --stdin runOnRemoteHostAsRoot" 2>&1
# ...

Expected output:

user
root

Actual output:

user
[sudo] password for user: sudo: runOnRemoteHostAsRoot: command not found

Solution

  • The suggestion from @Will is helpful in this instance, using sudo bash -c, then declaring and running the function:

    sudo bash -c "$(declare -f runOnRemoteHostAsRoot); runOnRemoteHostAsRoot"
    

    We'll use that line after passing the password through sshpass for passwordless login, like this:

    echo '${SSHPASS}' | sudo --stdin bash -c '$(declare -f runOnRemoteHostAsRoot); runOnRemoteHostAsRoot'`
    

    So using this in the above example:

    #!/bin/bash
    
    read SSHPASS
    export SSHPASS
    
    
    runOnRemoteHost() {
        # ...
        whoami
        # ...
    }
    # ...
    sshpass -e ssh -o PasswordAuthentication=yes "user@remotehost" "$(declare -f runOnRemoteHost); runOnRemoteHost" 2>&1
    # ...
    
    
    runOnRemoteHostAsRoot() {
        # ...
        whoami
        # ...
    }
    # ...
    sshpass -e ssh -o PasswordAuthentication=yes "user@remotehost" "echo '${SSHPASS}' | sudo --stdin bash -c '$(declare -f runOnRemoteHostAsRoot); runOnRemoteHostAsRoot'" 2>&1
    

    Output:

    user
    root