Skip to content

Instantly share code, notes, and snippets.

@derekp7
Last active October 13, 2025 14:00
Show Gist options
  • Select an option

  • Save derekp7/9978986 to your computer and use it in GitHub Desktop.

Select an option

Save derekp7/9978986 to your computer and use it in GitHub Desktop.

Revisions

  1. derekp7 revised this gist Apr 4, 2014. 1 changed file with 0 additions and 45 deletions.
    45 changes: 0 additions & 45 deletions gistfile2.sh
    Original file line number Diff line number Diff line change
    @@ -43,48 +43,3 @@ rpcsh() {
    $rmtmain \"\${rmtargs[@]}\"
    "
    }
    # rpcsh -- Runs a function on a remote host
    # This function pushes out a given set of variables and functions to
    # another host via ssh, then runs a given function with optional arguments.
    # Usage:
    # rpcsh -h remote_host [ -p ssh-port ] -u remote_login -v "variable list" \
    # -f "function list" -m mainfunc
    #
    # The "function list" is a list of shell functions to push to the remote host
    # (including the main function to execute, and any functions that it calls)
    # Use the "variable list" to send a group of variables to the remote host.
    # Finally "mainfunc" is the name of the function (from "function list")
    # to execute on the remote side. Any additional parameters specified gets
    # passed along to mainfunc.

    rpcsh() {
    if ! args=("$(getopt -l "rmthost:,rmthostport:,rmtlogin:,pushvars:,pushfuncs:,rmtmain:" -o "h:p:u:v:f:m:A" -- "$@")")
    then
    exit 1
    fi

    sshvars=( -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null )
    eval set -- "${args[@]}"
    while [ -n "$1" ]
    do
    case $1 in
    -h|--rmthost) rmthost=$2; shift; shift;;
    -p|--rmtport) sshvars=( "${sshvars[@]}" -p $2 ); shift; shift;;
    -u|--rmtlogin) rmtlogin=$2; shift; shift;;
    -v|--pushvars) pushvars=$2; shift; shift;;
    -f|--pushfuncs) pushfuncs=$2; shift; shift;;
    -m|--rmtmain) rmtmain=$2; shift; shift;;
    -A) sshvars=( "${sshvars[@]}" -A ); shift;;
    -i) sshvars=( "${sshvars[@]}" -i $2 ); shift; shift;;
    --) shift; break;;
    esac
    done
    rmtargs=( "$@" )

    ssh ${sshvars[@]} ${rmtlogin}@${rmthost} "
    $(declare -p rmtargs 2>/dev/null)
    $([ -n "$pushvars" ] && declare -p $pushvars 2>/dev/null)
    $(declare -f $pushfuncs 2>/dev/null)
    $rmtmain \"\${rmtargs[@]}\"
    "
    }
  2. derekp7 revised this gist Apr 4, 2014. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion gistfile1.md
    Original file line number Diff line number Diff line change
    @@ -18,7 +18,9 @@ Now, using "$(declare -f)", you can push this function to a remote host and exec
    ```ssh user@rmthost "$(declare -f hello); hello"```

    Output:
    ```Hello, world, I'm coming from rmthost.```
    ```
    Hello, world, I'm coming from rmthost.
    ```

    Bash will take care of all the escaping and quoting, load the function up, and leave the function in the environment to be executed. You can also push variables and arrays over, using "`$(declare -p varname)`". You can also list multiple functions and variables, if the main function relies on them, by listing them individually.

  3. derekp7 created this gist Apr 4, 2014.
    25 changes: 25 additions & 0 deletions gistfile1.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,25 @@
    Let's say you have a Bash shell script, and you need to run a series of operations on another system (such as via ssh). There are a couple of ways to do this.

    First, you can stage a child script on the remote system, then call it, passing along appropriate parameters. The problem with this is you will need to manually keep the remote script updated whenever you change it -- could be a bit of a challenge when you have something to execute on a number of remote servers (i.e., you have a backup script running on a central host, and it needs to put remote databases in hot backup mode before backing them up).

    Another option is to embed the commands you want to run remotely within the ssh command line. But then you run into issues with escaping special characters, quoting, etc. This is ok if you only have a couple commands to run, but if it is a complex piece of Bash code, it can get a bit unwieldy.

    So, to solve this, you can use a technique called rpcsh -- rpc in shell script, as follows:

    First, place the remote code segment into a shell function:
    ```sh
    hello() {
    echo "Hello, world, I'm coming from $(uname -n)."
    }
    ```

    Now, using "$(declare -f)", you can push this function to a remote host and execute it via ssh, as follows:

    ```ssh user@rmthost "$(declare -f hello); hello"```

    Output:
    ```Hello, world, I'm coming from rmthost.```

    Bash will take care of all the escaping and quoting, load the function up, and leave the function in the environment to be executed. You can also push variables and arrays over, using "`$(declare -p varname)`". You can also list multiple functions and variables, if the main function relies on them, by listing them individually.

    To make this more automatic, check out the attached rpcsh() function.
    90 changes: 90 additions & 0 deletions gistfile2.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,90 @@
    # rpcsh -- Runs a function on a remote host
    # This function pushes out a given set of variables and functions to
    # another host via ssh, then runs a given function with optional arguments.
    # Usage:
    # rpcsh -h remote_host [ -p ssh-port ] -u remote_login -v "variable list" \
    # -f "function list" -m mainfunc
    #
    # The "function list" is a list of shell functions to push to the remote host
    # (including the main function to execute, and any functions that it calls)
    # Use the "variable list" to send a group of variables to the remote host.
    # Finally "mainfunc" is the name of the function (from "function list")
    # to execute on the remote side. Any additional parameters specified gets
    # passed along to mainfunc.

    rpcsh() {
    if ! args=("$(getopt -l "rmthost:,rmthostport:,rmtlogin:,pushvars:,pushfuncs:,rmtmain:" -o "h:p:u:v:f:m:A" -- "$@")")
    then
    exit 1
    fi

    sshvars=( -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null )
    eval set -- "${args[@]}"
    while [ -n "$1" ]
    do
    case $1 in
    -h|--rmthost) rmthost=$2; shift; shift;;
    -p|--rmtport) sshvars=( "${sshvars[@]}" -p $2 ); shift; shift;;
    -u|--rmtlogin) rmtlogin=$2; shift; shift;;
    -v|--pushvars) pushvars=$2; shift; shift;;
    -f|--pushfuncs) pushfuncs=$2; shift; shift;;
    -m|--rmtmain) rmtmain=$2; shift; shift;;
    -A) sshvars=( "${sshvars[@]}" -A ); shift;;
    -i) sshvars=( "${sshvars[@]}" -i $2 ); shift; shift;;
    --) shift; break;;
    esac
    done
    rmtargs=( "$@" )

    ssh ${sshvars[@]} ${rmtlogin}@${rmthost} "
    $(declare -p rmtargs 2>/dev/null)
    $([ -n "$pushvars" ] && declare -p $pushvars 2>/dev/null)
    $(declare -f $pushfuncs 2>/dev/null)
    $rmtmain \"\${rmtargs[@]}\"
    "
    }
    # rpcsh -- Runs a function on a remote host
    # This function pushes out a given set of variables and functions to
    # another host via ssh, then runs a given function with optional arguments.
    # Usage:
    # rpcsh -h remote_host [ -p ssh-port ] -u remote_login -v "variable list" \
    # -f "function list" -m mainfunc
    #
    # The "function list" is a list of shell functions to push to the remote host
    # (including the main function to execute, and any functions that it calls)
    # Use the "variable list" to send a group of variables to the remote host.
    # Finally "mainfunc" is the name of the function (from "function list")
    # to execute on the remote side. Any additional parameters specified gets
    # passed along to mainfunc.

    rpcsh() {
    if ! args=("$(getopt -l "rmthost:,rmthostport:,rmtlogin:,pushvars:,pushfuncs:,rmtmain:" -o "h:p:u:v:f:m:A" -- "$@")")
    then
    exit 1
    fi

    sshvars=( -q -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null )
    eval set -- "${args[@]}"
    while [ -n "$1" ]
    do
    case $1 in
    -h|--rmthost) rmthost=$2; shift; shift;;
    -p|--rmtport) sshvars=( "${sshvars[@]}" -p $2 ); shift; shift;;
    -u|--rmtlogin) rmtlogin=$2; shift; shift;;
    -v|--pushvars) pushvars=$2; shift; shift;;
    -f|--pushfuncs) pushfuncs=$2; shift; shift;;
    -m|--rmtmain) rmtmain=$2; shift; shift;;
    -A) sshvars=( "${sshvars[@]}" -A ); shift;;
    -i) sshvars=( "${sshvars[@]}" -i $2 ); shift; shift;;
    --) shift; break;;
    esac
    done
    rmtargs=( "$@" )

    ssh ${sshvars[@]} ${rmtlogin}@${rmthost} "
    $(declare -p rmtargs 2>/dev/null)
    $([ -n "$pushvars" ] && declare -p $pushvars 2>/dev/null)
    $(declare -f $pushfuncs 2>/dev/null)
    $rmtmain \"\${rmtargs[@]}\"
    "
    }