2022-03-28 10:05:26 -07:00
|
|
|
#!/bin/bash
|
|
|
|
module_load ssh
|
2024-02-21 11:33:37 -08:00
|
|
|
module_load bundle
|
|
|
|
module_load helpers
|
|
|
|
module_load ssh-copy
|
|
|
|
|
|
|
|
|
|
|
|
remote_function () {
|
|
|
|
[[ $2 ]] && module_load $2
|
|
|
|
if declare -f $1; then
|
|
|
|
local file
|
|
|
|
file=$(mkrfilename function)
|
|
|
|
$(declare -f $1) > $file
|
|
|
|
echo $file
|
|
|
|
else
|
|
|
|
>&2 echo fatal: unable to source funtion $1, aborting
|
|
|
|
return 1
|
|
|
|
fi
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2022-03-28 10:05:26 -07:00
|
|
|
remote_script () {
|
2024-02-21 11:33:37 -08:00
|
|
|
|
|
|
|
local sshargs;local user;local supass;local cfn; local rfn; local args;
|
2024-02-21 14:47:54 -08:00
|
|
|
local script; local host; local dr; local supass; local env_vars;
|
|
|
|
local login; local slogin
|
|
|
|
local hostname; local bscript; local ruser; local usesudo; local save
|
2024-02-21 11:33:37 -08:00
|
|
|
|
|
|
|
help() {
|
|
|
|
|
|
|
|
cat <<EOF
|
|
|
|
usage: remote_script <remote_script options> host script <script args> -- <ssh script options>
|
|
|
|
host and script are required, script can be either path to a file containing a script to a UCI module
|
|
|
|
-s, execute remote script using sudo
|
|
|
|
-f, run a function in the passed script, otherwise script is assumed to be bash executed.
|
|
|
|
-d, dry run. don't run the rscript just output the command that will be run
|
|
|
|
-u, remote user to run script as. default is ssh host user or root if using sudo
|
|
|
|
-p, password for ssh login, will also be used for sudo assuming remote user is in sudo group
|
|
|
|
-x, create script from available function instead of module or file
|
2024-02-21 14:47:54 -08:00
|
|
|
-l, use login shell on remote
|
|
|
|
-e, set some environment variables to run
|
2024-02-21 11:33:37 -08:00
|
|
|
-h, this help text
|
|
|
|
EOF
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
# parse ssh arguments from the rest
|
|
|
|
debug $( ( IFS=$','; echo all arguments: "$*" ) )
|
|
|
|
for ((d=1; d<$#; ++d)); do
|
|
|
|
[[ ${!d} == "--" ]] && break
|
|
|
|
done
|
|
|
|
|
|
|
|
if [[ $d -lt $# ]]; then # if there are extra ssh arguments
|
|
|
|
debug found -- at $d
|
|
|
|
sshargs=("${@:$d+1:$#}")
|
|
|
|
debug $( ( IFS=$','; echo "ssh arguments: ${sshargs[*]}" ) )
|
|
|
|
# [[ ! ${sshargs[0]} ]] && { echo missing remote machine, must provide at least a hostname, -- hostname; return 3; }
|
|
|
|
args=("${@:1:$d-1}")
|
|
|
|
# reset script arguments to just those before --
|
|
|
|
set -- "${args[@]}"
|
|
|
|
debug $( ( IFS=$','; echo remaining arguments to parse: "$*" ) )
|
|
|
|
fi
|
|
|
|
|
|
|
|
# parse remote_script options
|
|
|
|
local OPTION
|
|
|
|
local OPTARG
|
|
|
|
local OPTIND
|
2024-02-21 14:47:54 -08:00
|
|
|
while getopts 'le:hdu:sf:p:x:' OPTION; do
|
2024-02-21 11:33:37 -08:00
|
|
|
# echo OPTION $OPTION ARG $OPTARG INDX $OPTIND
|
|
|
|
case "$OPTION" in
|
|
|
|
s)
|
|
|
|
# using sudo, password will come from ssh user password or if you supply it with -p
|
|
|
|
usesudo=true
|
|
|
|
;;
|
2022-03-28 10:05:26 -07:00
|
|
|
f)
|
2024-02-21 11:33:37 -08:00
|
|
|
# run a function within the script
|
|
|
|
# any function arguments appear after script
|
|
|
|
cfn="-f $OPTARG"
|
|
|
|
;;
|
|
|
|
d)
|
|
|
|
# dry run
|
|
|
|
dr=true
|
|
|
|
;;
|
2024-02-21 14:47:54 -08:00
|
|
|
e)
|
2024-02-21 14:51:14 -08:00
|
|
|
env_vars+=" $OPTARG"
|
2024-02-21 14:47:54 -08:00
|
|
|
;;
|
2022-03-28 10:05:26 -07:00
|
|
|
u)
|
2024-02-21 11:33:37 -08:00
|
|
|
# run remote command as another user
|
|
|
|
ruser=$OPTARG
|
|
|
|
# usesudo=true
|
|
|
|
;;
|
2024-02-21 14:47:54 -08:00
|
|
|
l)
|
|
|
|
login="bash -l"
|
|
|
|
;;
|
2024-02-21 11:33:37 -08:00
|
|
|
x)
|
|
|
|
rfn=$OPTARG
|
2022-03-28 10:05:26 -07:00
|
|
|
;;
|
2023-02-09 09:26:51 -08:00
|
|
|
p)
|
2024-02-21 11:33:37 -08:00
|
|
|
# password of sudo account for running as root or other user
|
|
|
|
# will force running as root on remote if ruser is not specified
|
|
|
|
supass=$OPTARG
|
|
|
|
;;
|
|
|
|
h)
|
|
|
|
help
|
|
|
|
return 0
|
|
|
|
;;
|
2022-03-28 10:05:26 -07:00
|
|
|
*)
|
2024-02-21 11:33:37 -08:00
|
|
|
>&2 echo fatal: unknown remote script option $OPTION, aborting
|
|
|
|
help
|
2022-03-28 10:05:26 -07:00
|
|
|
return 1
|
|
|
|
;;
|
|
|
|
esac
|
2024-02-21 11:33:37 -08:00
|
|
|
done
|
|
|
|
|
|
|
|
shift $((OPTIND - 1))
|
|
|
|
|
|
|
|
[[ $# -lt 1 ]] && echo fatal: remote_script requires a 'host' && help && return 1
|
|
|
|
|
2024-02-21 14:47:54 -08:00
|
|
|
host=$1; shift 1
|
2024-02-21 11:33:37 -08:00
|
|
|
[[ ! $host ]] && echo fatal: no host was passed unable to excute a remote script && return 3
|
|
|
|
user=$(get_user_host $host)
|
|
|
|
[[ ! $user ]] && echo fatal: unable to determine user at host $host, aborting remote script && return 4
|
|
|
|
hostname=$(get_hostname_host $host)
|
|
|
|
|
|
|
|
# script can come from
|
|
|
|
if [[ $rfn ]]; then
|
|
|
|
if ! declare -f $rfn >/dev/null; then
|
2024-02-21 14:47:54 -08:00
|
|
|
if ! module_load $1; then
|
|
|
|
[[ -f $1 ]] && source $1
|
2024-02-21 11:33:37 -08:00
|
|
|
fi
|
|
|
|
if ! declare -f $rfn >/dev/null; then echo fatal: remote-script, unable to source funtion $rfn, aborting; return 1; fi
|
|
|
|
shift
|
2022-03-28 10:05:26 -07:00
|
|
|
fi
|
2024-02-21 11:33:37 -08:00
|
|
|
local file
|
|
|
|
script=$(mkrfilename temp_function)
|
|
|
|
declare -f $rfn > $script
|
|
|
|
cfn="-f $rfn"
|
|
|
|
else
|
2024-02-21 14:47:54 -08:00
|
|
|
script=$1
|
2024-02-21 11:33:37 -08:00
|
|
|
shift 1
|
|
|
|
fi
|
2024-02-21 14:47:54 -08:00
|
|
|
[[ ! $script ]] && echo fatal: must pass a script to remote run && help && return 1
|
2024-02-21 11:33:37 -08:00
|
|
|
|
|
|
|
debug echo host: $host user: $user hostname:$hostname script:$script function to run: $cfn
|
|
|
|
|
|
|
|
bscript=$(mkrfilename bundle_script )
|
|
|
|
if ! bundle -c $cfn $script $bscript; then
|
|
|
|
>&2 echo fatal: remote_script unable to bundle script for sending, aborting; return 1;
|
|
|
|
fi
|
|
|
|
|
2024-02-21 14:47:54 -08:00
|
|
|
if [[ $usesudo ]] || [[ $supass ]]; then
|
|
|
|
[[ $usesudo ]] && supass=$(parse_option "${sshargs[*]}" -p)
|
|
|
|
if [[ $supass ]]; then
|
|
|
|
[[ $login ]] && login="" && slogin="-i"
|
|
|
|
usesudo="echo '${supass}' | sudo $slogin -u ${ruser:-root} --stdin 2>/dev/null"
|
|
|
|
echo remote script to be run as ${ruser:-root} using sudo
|
|
|
|
else
|
|
|
|
echo sudo requested but no sudo password supplied, aborting
|
|
|
|
return 5
|
|
|
|
fi
|
|
|
|
fi
|
2024-02-21 11:33:37 -08:00
|
|
|
|
|
|
|
debug remote script arguments $(remote_args "$@")
|
|
|
|
debug ssh arguments $(remote_args "${sshargs[@]}")
|
|
|
|
|
|
|
|
rscript=${save:-$(mkrfilename REMOTE_SCRIPT)}
|
|
|
|
if sshcp -d $host $bscript $rscript -- "${sshargs[@]}"; then
|
|
|
|
# make remote script excuteable
|
|
|
|
ssh "${sshargs[@]}" "$host" "chmod +x $rscript"
|
|
|
|
# run the script
|
2024-02-21 14:47:54 -08:00
|
|
|
ssh "${sshargs[@]}" "$host" "$usesudo" $login "$env_vars" "$rscript" "$(remote_args "$@")"
|
2024-02-21 11:33:37 -08:00
|
|
|
# now delete it, save script if passed an explicit name
|
|
|
|
if ! ssh "${sshargs[@]}" $host rm -f $rscript; then echo unable to delete temporary remote file at $host:$rscript; fi
|
|
|
|
# ssh "${sshargs[@]}" "$host" "cat $rscript"
|
2022-03-28 10:05:26 -07:00
|
|
|
else
|
2024-02-21 11:33:37 -08:00
|
|
|
>&2 echo fatal: remote_script failed because script could not be copied; return 1;
|
|
|
|
fi
|
2022-03-28 10:05:26 -07:00
|
|
|
|
2024-02-21 11:33:37 -08:00
|
|
|
rm -f $bscript
|
|
|
|
[[ $rfn ]] && [[ "${script}" =~ "temp_function" ]] && rm -f $script
|
2022-03-28 10:05:26 -07:00
|
|
|
|
|
|
|
}
|
2024-02-21 11:33:37 -08:00
|
|
|
# END REMOTE SCRIPT
|
2022-03-28 10:05:26 -07:00
|
|
|
|
2023-02-09 09:26:51 -08:00
|
|
|
|
|
|
|
# can be used with a file or HEREDOC
|
|
|
|
# todo test with < $file or with a pipe
|
|
|
|
remote_stdin () {
|
|
|
|
local file
|
|
|
|
# echo args $@
|
2024-02-21 11:33:37 -08:00
|
|
|
file=$( mkrfilename remote_script )
|
2023-02-09 09:26:51 -08:00
|
|
|
cat > $file
|
2024-02-21 11:33:37 -08:00
|
|
|
remote_script $1 "$file" "$@"
|
|
|
|
rm -f $file &> /dev/null
|
2023-02-09 09:26:51 -08:00
|
|
|
}
|
|
|
|
|
2022-03-28 10:05:26 -07:00
|
|
|
# # if script was executed then call the function
|
|
|
|
(return 0 2>/dev/null) ||remote_script $@
|
|
|
|
|
2023-12-14 21:31:40 -08:00
|
|
|
|
|
|
|
|
|
|
|
|
2024-02-21 11:33:37 -08:00
|
|
|
|