diff --git a/sshsudo b/sshsudo deleted file mode 100755 index c63bebb..0000000 --- a/sshsudo +++ /dev/null @@ -1,184 +0,0 @@ -#!/bin/bash -# -# sshsudo: 1.0 -# Author: jiwu.liu@gmail.com -# -# The script executes sudo command on one or more remote computers. -# Its arguments are the names to remote sudoers and remote computers. -# The script read the password from the standard input, which should -# be the same for all sudoer accounts. No password is explicitly shown -# in the terminal or logged to files. -# If the command is a local shell script, use '-r' to copy it to -# the remote computers to execute. A temporary script file will be -# automatically created for this purpose. -# -# -# TO DO: It can not execute a command that use the shell special charaters -# on the remote computer, such as & ; ! *, because all arguments -# are wrapped with ''. That means, all special characters have only -# literal meanings. In the case when they are needed, use a script -# instead of a command. -# -# Example:sshsudo foo@bar.net apt-get check -# sshsudo -r foo@bar.net myscript.sh - - -usage() -{ - local ProgName=$1; - echo "Usage: $ProgName -r -v [-u user] AccountList Command [Arguments]" - echo " -u Set the default user unless it is given within remote account list" - echo " -r Copy the command(usually the path to local script) to remote computers before execution" - echo " -v Verbose output" - echo " AccountList: [user1@]computer1,[user2@]computer2,[user3@]computer3,..." - echo " or the name to file which contains accounts(user@computer) in separate lines" - echo " Command: The Command/Script to be executed" - echo " Arguments: All arguments to be passed to command." -} - -pipewrap() -{ - # This function reads in the input from a terminal and output the same. - # The only purpose is to insert PASSWORD for "sudo -S" command. - # After initially insert the password, it simply copy input from terminal - # and send it to ssh command directly - echo $1 # which is password - local lockFile=$2; - while true; do - # The function will exit when output pipe is closed, - if [ ! -e $lockFile ]; then - return 0 - fi - # i.e., the ssh - read -t 1 line - if [ $? -eq 0 ]; then - # successfully read - echo $line - fi - done -} - -runsudo () -{ - # receive its arguments - local ACCOUNT=$1; - local PASSWORD=$2; - local COMMAND=$3; - local ARGUMENTS=$4; - local DEFAULTUSER=$5; - local COPY=$6; - local VERBOSE=$7; - - # Parse account which has the form user@computer.domain - local REMOTEUSER=${ACCOUNT%%@*} - local REMOTECOMPUTER=${ACCOUNT#*@} - local REMOTESCRIPT= - local REMOTECOMMAND=$COMMAND - if [ $REMOTEUSER = $REMOTECOMPUTER ]; then - # There is no @, i.e., only computer name is given - REMOTEUSER=$DEFAULTUSER - fi - echo =========================${REMOTEUSER}@$REMOTECOMPUTER: sudo $COMMAND $ARGUMENTS - if [ $COPY -ne 0 ]; then - # Make a script + seconds since 1970-01-01 - REMOTESCRIPT=/tmp/$COMMAND`date +%s` - if [ $VERBOSE -ne 0 ]; then - echo $REMOTECOMPUTER: Secure copy \"$COMMAND\" to \"$REMOTESCRIPT\" - fi - # Copy to remote computer. Quote target name on the remote computer for script name - # that contains " " - sshpass -p "$PASSWORD" scp "$COMMAND" "$REMOTEUSER@$REMOTECOMPUTER:'$REMOTESCRIPT'" - REMOTECOMMAND=$REMOTESCRIPT - fi - - # Assume we are lucky, result is fine. - local RES=DONE - # Invalidate the sudo timestamp. Simplify the situation. Henceforth sudo always ask for a password - sshpass -p "$PASSWORD" ssh "$REMOTEUSER@$REMOTECOMPUTER" "sudo -K" - - # Use lock file to inform pipewrap function to exit. - local lockFile=`mktemp` - eval pipewrap '$PASSWORD' '$lockFile' | (sshpass -p "$PASSWORD" ssh "$REMOTEUSER@$REMOTECOMPUTER" "sudo -S '$REMOTECOMMAND' $ARGUMENTS"; rm "$lockFile") - - if [ $? -ne 0 ]; then - RES=FAILED - fi - if [ $COPY -ne 0 ]; then - sshpass -p $PASSWORD ssh "$REMOTEUSER@$REMOTECOMPUTER" rm \'$REMOTESCRIPT\' - if [ $VERBOSE -ne 0 ]; then - echo Remove temporary script \"$REMOTESCRIPT\" at [$REMOTECOMPUTER] - fi - fi - echo ----------------------------------${RES}!!---------------------------------------- -} - - -#=====================================Main Script======================================== -# -# Set default values for variables -COMMAND= -ARGUMENTS= -COPY=0 -VERBOSE=0 -ACCOUNTLIST= -DEFAULTUSER=$USER - -# Parse the command line arguments with '-' -while getopts u:hrv o ; do - case "$o" in - [?]) usage $0 - exit 1;; - h) usage $0 - exit 0;; - u) DEFAULTUSER=$OPTARG;; - v) VERBOSE=1;; - r) COPY=1;; - esac -done - -# Read the rest command line arguments -if [ $(($#-$OPTIND+1)) -lt 2 ]; then - echo Error: Account list and command have to be in the arguments - usage $0 - exit 4 -fi - -shift $(($OPTIND-1)) -ACCOUNTLIST=$1 -shift -COMMAND=$1 -shift -for PARAM; do - ARGUMENTS=$ARGUMENTS\'$PARAM\'" " -done - -# Check the validity of the script command if remote copy is needed -if [ $COPY -ne 0 ]; then - if [ ! -e "$COMMAND" ]; then - echo \"$COMMAND\" does not exist. - exit 3 - fi - if [ ! -x "$COMMAND" ]; then - echo \"$COMMAND\" can not be executed. - exit 3 - fi -fi - -# Read in the password from the STDIN -read -s -p "Please enter your password:" PASSWORD -echo - -# Start running -if [ -e $ACCOUNTLIST ]; then # read accounts from a file - for ACCOUNT in `cat $ACCOUNTLIST`; do - runsudo "$ACCOUNT" "$PASSWORD" "$COMMAND" "$ARGUMENTS" "$DEFAULTUSER" "$COPY" "$VERBOSE"; - done - -else # ACCOUNTLIST is a comma separated list of user@computer strings. - # Change the internal separation field. - IFS=, - for ACCOUNT in $ACCOUNTLIST; do - runsudo "$ACCOUNT" "$PASSWORD" "$COMMAND" "$ARGUMENTS" "$DEFAULTUSER" "$COPY" "$VERBOSE"; - done -fi -#EOF