pax_global_header00006660000000000000000000000064135727536760014537gustar00rootroot0000000000000052 comment=8b442d78160ecc5093b75a6a3a92ef2a1ec5b5e1 runoverssh-3.0.3/000077500000000000000000000000001357275367600137605ustar00rootroot00000000000000runoverssh-3.0.3/CHANGELOG000066400000000000000000000007031357275367600151720ustar00rootroot000000000000003.0.3: - Updated program description 3.0.2: - Updated program description 3.0.1: - Updated documentation 3.0: - POSIX compliance - No longer uses sshpass by default - Added --shell option - Added --verbose option 2.2: - added option to pass arguments to the script file (ex: --script "test.sh" --args "arg1 arg2") 2.1: - now checks for sshpass only when '-n' option is not set - improved error messages - added default Bash flags in README runoverssh-3.0.3/README.md000066400000000000000000000051331357275367600152410ustar00rootroot00000000000000## Description POSIX-compliant shell script for easily running shell commands and scripts over SSH. ### Installation #### Debian/Ubuntu ``` sudo apt install runoverssh ``` #### Manually ``` sudo curl -L "https://raw.githubusercontent.com/yuriescl/runoverssh/master/runoverssh" -o /usr/local/bin/runoverssh && chmod +x /usr/local/bin/runoverssh ``` ### Usage ``` $ runoverssh [OPTIONS] USERNAME COMMAND HOSTS... Options: -g, --globalpw Prompt a global password for all connections -s, --script FILE Read commands from a script file, disables the default COMMAND argument -r, --hostsfile FILE Read the list of hosts from a file (one host per line), disables the default HOSTS argument -a, --args ARGS Arguments (in a single string) to be passed to the script file. -q, --quiet Disable all screen output, except for password prompts. If logfile is set, output is written there -v, --verbose Print verbose messages --shell SHELL Remote shell to be used. Supported values: sh, bash default: bash --shellflags FLAGS Remote shell flags default: '' --sshflags FLAGS Local SSH flags default: -o ConnectTimeout=5 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null --logfile FILE Append SSH output to a file ``` ### Default behavior * SSH flags: `-o ConnectTimeout=5 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null` * Uses `bash` as the remote shell ### Global Password A global password can be used for all SSH connections. It requires `sshpass` to be installed. See the `-g` flag. ### Examples Restart Apache webserver in two hosts ``` runoverssh root "systemctl restart apache2" webserver webserver2 ``` Reboot three hosts, which contain the same root password. Writes the SSH output to `reboot.log`. ``` runoverssh --logfile reboot.log --globalpw root "reboot" host1 host2 host3 ``` Run puppet agent in all nodes listed in `puppet-nodes`, supressing the output ``` runoverssh -q -g -r puppet-nodes root "puppet agent -t" ``` Check git status on devmachine ``` runoverssh remoteuser "cd git-project && git status" devmachine ``` Run backup script in all hosts listed in a file ``` runoverssh -g --script backup.sh --hostsfile hostlist remoteuser ``` runoverssh-3.0.3/runoverssh000077500000000000000000000236101357275367600161260ustar00rootroot00000000000000#!/usr/bin/env sh # This program runs a shell command/script over SSH in a remote host or list of hosts # Copyright (C) 2017 Yuri Escalianti (https://github.com/yuriescl/runoverssh) # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # # Script name script_name=`basename "$0"` script_alias=`basename -s .sh "$0"` # Print help print_help() { error "Usage: $script_name [OPTIONS] USERNAME COMMAND HOSTS..." error "Options:" error "" error " -g, --globalpw Prompt a global password for all connections" error " -s, --script FILE Read commands from a script file, disables" error " the default COMMAND argument" error " -r, --hostsfile FILE Read the list of hosts from a file (one host" error " per line), disables the default HOSTS argument" error " -a, --args ARGS Arguments (in a single string) to be passed to" error " the script file." error " -q, --quiet Disable all screen output, except for password" error " prompts. If logfile is set, output is written" error " there" error " -v, --verbose Print verbose messages" error " --shell SHELL Remote shell to be used. Supported values:" error " sh, bash" error " default: bash" error " --shellflags FLAGS Remote shell flags" error " default: ''" error " --sshflags FLAGS Local SSH flags" error " default: -o ConnectTimeout=5" error " -o StrictHostKeyChecking=no" error " -o UserKnownHostsFile=/dev/null" error " --logfile FILE Append SSH output to a file" error "" error "Examples:" error "" error " runoverssh root 'systemctl restart apache2' server1 server2" error "" error " runoverssh --logfile runoverssh.log --quiet --globalpw root 'reboot' host1 host2 host3" error "" error " runoverssh remoteuser 'cd git-project && git status' devmachine" error "" error " runoverssh --script myscript.sh --hostsfile hostlist remoteuser" error "" error " runoverssh --script myscript.sh --args '-q -s -t' --hostsfile hostlist remoteuser" error "" error "Bugs or Requests: https://github.com/yuriescl/runoverssh/issues" } error() { >&2 echo "$@" } read_password() { printf "$1" stty -echo IFS= read -r password stty echo printf '\n' } # Standard parameters username="" remote_command="" # Optional parameters scriptfile="" # -s , --script args="" # -a , --args hostsfile="" # -r , --hostsfile logfile="/dev/null" # --logfile globalpw="" # -g, --globalpw shell="bash" shellflags="" # --shellflags sshflags="-o ConnectTimeout=5 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" # --sshflags quiet="" # -q , --quiet verbose="" if [ "$1" = "--help" ]; then print_help exit 0 else # Check parameter count if [ $# -lt 3 ]; then error "Usage: $script_name [OPTIONS] USERNAME COMMAND HOSTS..." error "Use '$script_name --help' for command help and examples." exit 1 fi fi # Read parameters is_first="" waiting_option="" for parameter do if [ -n "$is_first" ] && [ -n "$waiting_option" ]; then # Assign the option case "$waiting_option" in "-s" | "--script") scriptfile="$parameter" ;; "-a" | "--args") args="$parameter" ;; "-r" | "--hostsfile") hostsfile="$parameter" ;; "--logfile") logfile="$parameter" ;; "--shell") shell="$parameter" ;; "--shellflags") shellflags="$parameter" ;; "--sshflags") sshflags="$parameter" ;; esac waiting_option="" else # first or not waiting option is_first="no" case "$parameter" in "-s" | "--script" | "-a" | "--args" | "-r" | "--hostsfile" | "--logfile" | "--sshflags" | "--shellflags" | "--shell") waiting_option="$parameter" ;; "-g" | "--globalpw") globalpw="true" ;; "-q" | "--quiet") quiet="true" ;; "-v" | "--verbose") verbose="true" ;; *) case "$parameter" in "--"*) error "Error: invalid option '$parameter'. Exiting." exit 1 ;; "-"*) error "Error: invalid option '$parameter'. Exiting." exit 1 ;; *) ;; esac # Read the remaining arguments if [ -z "$username" ]; then username=${parameter} else if [ -z "$scriptfile" ] && [ -z "$remote_command" ]; then remote_command="$parameter" else hosts="${hosts:+${hosts} }${parameter}" # append to string fi #command fi #username waiting_option="" esac fi # ! is_first and is waiting done if [ -n "$verbose" ]; then echo "username: $username" echo "remote_command: $remote_command" echo "scriptfile: $scriptfile" echo "args: $args" echo "hostsfile: $hostsfile" echo "logfile: $logfile" echo -n "globalpw: " if [ -n "$globalpw" ]; then echo yes; else echo no; fi echo "sshflags: $sshflags" echo "shellflags: $shellflags" echo -n "quiet: " if [ -n "$quiet" ]; then echo yes; else echo no; fi echo -n "verbose: " if [ -n "$verbose" ]; then echo yes; else echo no; fi fi # Check parameter and argument consistency if [ -n "$waiting_option" ]; then error "Error: missing value for '$waiting_option' parameter. Exiting." exit 1 fi if [ -z "$username" ]; then error "Error: please specify the username to be used in SSH. Exiting." exit 1 fi if [ -z "$scriptfile" ] && [ -z "$remote_command" ] ; then error "Error: please specify the command or script file ('-s') to be executed over SSH. Exiting." exit 1 fi if [ -n "$scriptfile" ] && [ -n "$remote_command" ] ; then error "Error: parameter conflict: do not put a command as argument when also specifying a script as parameter. Exiting." exit 1 fi if [ -n "$args" ] && [ -z "$scriptfile" ]; then error "Error: arguments specified but no script file provided. Exiting." exit 1 fi if [ -z "$hostsfile" ] && [ -z "$hosts" ]; then error "Error: please specify at least one target host or use the '--hostsfile' option. Exiting." exit 1 fi if [ -n "$hostsfile" ] && [ -n "$hosts" ]; then error "Error: parameter conflict: do not list hosts as arguments when also specifying a hostsfile as parameter. Exiting." exit 1 fi # Check file readability (if specified to read from a file) if [ -n "$hostsfile" ] && [ ! -r "$hostsfile" ]; then error "Error: can't read the hosts file '${hostsfile}'. Exiting." exit 1 fi if [ -n "$scriptfile" ] && [ ! -r "$scriptfile" ]; then error "Error: can't read the script file '${scriptfile}'. Exiting." exit 1 fi if [ "$shell" != "sh" ] && [ "$shell" != "bash" ]; then error "Error: shell '$shell' is not supported" exit 1 fi # Check log file if [ -d "$logfile" ]; then error "Error: log file '$logfile' is a directory. Exiting." exit 1 fi # Check dependencies command -v "ssh" >/dev/null 2>&1 || { error "Error: program 'ssh' not found. Exiting."; exit 1; } if [ -n "$globalpw" ]; then command -v "sshpass" >/dev/null 2>&1 || { error "Error: program 'sshpass' is required when using the '--globalpw' option. Exiting."; exit 1; } fi if [ -n "$globalpw" ]; then read_password "Global password for user ${username}: " fi if [ -n "$hostsfile" ]; then while read host; do hosts="${hosts:+${hosts} }${host}" # append to string done<"$hostsfile" fi # Connect to each host and execute the command/script if [ -z "$globalpw" ]; then for host in ""$hosts""; do if [ -z "$quiet" ]; then echo "Connecting as ${username}@${host}..."; fi if [ -n "$scriptfile" ]; then if [ -n "$quiet" ]; then ssh ${sshflags} ${username}@${host} "${shell} ${shellflags} -s" < "${scriptfile}" "${args}" >> /dev/null 2>&1 else ssh ${sshflags} ${username}@${host} "${shell} ${shellflags} -s" < "${scriptfile}" "${args}" 2>&1 | tee -a "${logfile}" fi else if [ -n "$quiet" ]; then ssh ${sshflags} ${username}@${host} "${shell} ${shellflags} -c \"${remote_command}\"" >> /dev/null 2>&1 else ssh ${sshflags} ${username}@${host} "${shell} ${shellflags} -c \"${remote_command}\"" 2>&1 | tee -a "${logfile}" fi fi done else for host in ""$hosts""; do if [ -z "$quiet" ]; then echo "Connecting as ${username}@${host}..."; fi if [ -n "$scriptfile" ]; then if [ -n "$quiet" ]; then sshpass -p "${password}" ssh ${sshflags} ${username}@${host} "${shell} ${shellflags} -s" < "${scriptfile}" "${args}" >> /dev/null 2>&1 else sshpass -p "${password}" ssh ${sshflags} ${username}@${host} "${shell} ${shellflags} -s" < "${scriptfile}" "${args}" 2>&1 | tee -a "${logfile}" fi else if [ -n "$quiet" ]; then sshpass -p "${password}" ssh ${sshflags} ${username}@${host} "${shell} ${shellflags} -c \"${remote_command}\"" >> /dev/null 2>&1 else sshpass -p "${password}" ssh ${sshflags} ${username}@${host} "${shell} ${shellflags} -c \"${remote_command}\"" 2>&1 | tee -a "${logfile}" fi fi done fi exit 0 # end. runoverssh-3.0.3/runoverssh.1000066400000000000000000000025461357275367600162670ustar00rootroot00000000000000.TH RUNOVERSSH 1 .SH NAME runoverssh \- POSIX-compliant shell script for easily running shell commands and scripts over SSH .SH SYNOPSIS .B runoverssh [\fBOPTIONS\fR] USERNAME COMMAND HOSTS... .SH DESCRIPTION .B runoverssh POSIX-compliant shell script for easily running shell commands and scripts over SSH. .SH OPTIONS .TP .BR \-g ", " \-\-globalpw Prompt a global password for all connections .TP .BR \-s ", " \-\-script " " [file] Read commands from a script file, disables the default COMMAND argument .TP .BR \-r ", " \-\-hostsfile " " [file] Read the list of hosts from a file (one host per line), disables the default HOSTS argument .TP .BR \-a ", " \-\-args " " [args] Arguments (in a single string) to be passed to the script file. .TP .BR \-q ", " \-\-quiet " " Disable all screen output, except for password prompts. If logfile is set, output is written there .TP .BR \-v ", " \-\-verbose " " Print verbose messages .TP .BR \-\-shell " " [shell] Remote shell to be used. Supported values: sh, bash. Default: bash .TP .BR \-\-shellflags " " [shellflags] Remote shell flags. Default: '' .TP .BR \-\-sshflags " " [shellflags] Local SSH flags. Default: -o ConnectTimeout=5 -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null .TP .BR \-\-logfile " " [file] Append SSH output to a file .SH AUTHOR runoverssh was written by Yuri Escalianti.