lion_bash
lion_bash

Reputation: 1409

Bash using optional parameters

I am trying to create a function that will take in $PASS, $USER, and $COMMAND as inputs the $USER and $PASS are optional, meaning it will use default username and passwords if non was supplied as parameters. Here is my function

function exec_ssh_command() {
    local PASS=${1:-${ROOT_PW}};    # use argument supplied or default root pw
    local USER=${2:-${ROOT_USER}};
    shift 2
    local COMMAND=$@

    echo "Executing command: ${COMMAND}..."

    sshpass -p ${PASS} ssh ${USER}@${ADDRESS} ${COMMAND}
}

If this is run without $1 and $2 arguments it breaks the function, so the output would be something like sshpass -p ls -ltr ssh {USER}@{ADDRESS} ls -ltr if my $COMMAND is ls -ltr

How can I get around this?

Upvotes: 0

Views: 49

Answers (3)

anishsane
anishsane

Reputation: 20980

You can use getopts to parse positional parameters as below:

exec_ssh_command() {
    local OPTIND=0
    local OPTARG OPTION
    local pass=${DEFAULT_PASS} user=${DEFAULT_USER}
    while getopts "u:p:" OPTION; do
        case "$OPTION" in
        u) user=$OPTARG;;
        p) pass=$OPTARG;;
        esac
    done

    sshpass -p "$pass" ssh "${user}@${ADDRESS}" "${@:OPTIND}"
}

Sample usages:

exec_ssh_command -u my_user -p my_password ls -ltr
exec_ssh_command -p my_password ls -ltr
exec_ssh_command -p my_password ls -ltr
exec_ssh_command ls -ltr

Explanation: See help getopts on a bash prompt for the complete info. (Any explanation I would have added here would have been just a snippet from the same output.)

Upvotes: 2

William Pursell
William Pursell

Reputation: 212248

If you want to make the convention that the function is to be called: exec_ssh_command [[user] password] command, you could implement it like:

exec_ssh_command() {
    local pass user
    case $# in
    2) pass=${ROOT_PW}; user="$1"; shift 1;;
    1) pass=${ROOT_PW}; user=${ROOT_USER};;
    *) pass="$1"; user="$2"; shift 2;; 
    esac
    sshpass -p "$pass" ssh "${user}@${ADDRESS?}" "$@"
}

or (basically the same thing, just a stylistic difference):

exec_ssh_command() {
    local pass user
    case $# in
    2) user="$1"; shift 1;;
    1) ;;
    *) pass="$1"; user="$2"; shift 2;;
    esac
    sshpass -p "${pass:-$ROOT_PW}" ssh "${user:-$ROOT_USER}@${ADDRESS?}" "$@"
}

Upvotes: 0

Matthieu
Matthieu

Reputation: 3097

If you don't provide at least two arguments, the shift 2 can fail because there are not enough arguments to shift. Try testing them before:

if [[ -n "$1" ]] ; then
    PASS="$1"
    shift
else
    PASS="$ROOT_PW"
fi
if [[ -n "$1" ]] ; then
    USER="$1"
    shift
else
    USER="$ROOT_USER"
fi
COMMAND=$@
...

Upvotes: 0

Related Questions