11

I have script where i need to display usage command in case user miss any mandatory information while executing script.

Usage : Script -s <server> -i <instance> -u <user> -p <password> <query> -w <warning value> -c <critical value>

With explanation about all the OPTIONS

I'm getting values from arguments as below variables fashion. But I want this usage with validations in shell script.

SERVER=$1
INSTANCE=$2
USER=$3
DB_PASSWD=$4
QUERY=$5
VAL_WARN=$6
VAL_CRIT=$7

I have tried using getopts, But failed to use since <query> doesn't have a -q parameter before passing the value.

I have tried finding all other ways, But everyone suggested getopts which is not feasible solution for me.

Please help me on this..

William Pursell
  • 204,365
  • 48
  • 270
  • 300
San
  • 223
  • 1
  • 6
  • 15
  • 1
    One of the merits of option letters is that it allows the user to put the items in any order. If the order is fixed, there's no need to bother with options such as `-s`; that just makes the user type extra for essentially no benefit. I note that the server string is `$2` (not `$1`) in the raw command line. Can you not regularize your command so that the `-q` is needed, or so that the query is the last argument? Do any of the options have sensible defaults? If so, use them instead of demanding that a user types 13 arguments. Your users will thank you, and your script will be easier to write. – Jonathan Leffler Feb 21 '13 at 02:00

5 Answers5

23

Use shift to iterate through all of your arguments, something like:

#!/bin/sh

usage ()
{
  echo 'Usage : Script -s <server> -i <instance> -u <user> -p <password>'
  echo '                  <query> -w <warning value> -c <critical value>'
  exit
}

if [ "$#" -ne 13 ]
then
  usage
fi

while [ "$1" != "" ]; do
case $1 in
        -s )           shift
                       SERVER=$1
                       ;;
        -i )           shift
                       INSTANCE=$1
                       ;;
        -u )           shift
                       USER=$1
                       ;;
        -p )           shift
                       PASSWORD=$1
                       ;;
        -w )           shift
                       WARNINGVAL=$1
                       ;;
        -c )           shift
                       CRITICVAL=$1
                       ;;
        * )            QUERY=$1
    esac
    shift
done

# extra validation suggested by @technosaurus
if [ "$SERVER" = "" ]
then
    usage
fi
if [ "$INSTANCE" = "" ]
then
    usage
fi
if [ "$USER" = "" ]
then
    usage
fi
if [ "$PASSWORD" = "" ]
then
    usage
fi
if [ "$QUERY" = "" ]
then
    usage
fi
if [ "$WARNINGVAL" = "" ]
then
    usage
fi
if [ "$CRITICVAL" = "" ]
then
    usage
fi

echo "ALL IS WELL. SERVER=$SERVER,INSTANCE=$INSTANCE,USER=$USER,PASSWORD=$PASSWORD,QUERY=$QUERY,WARNING=$WARNINGVAL,CRITIC=$CRITICVAL"

Should do the trick.

EDIT: added argument validation in the script as suggested by @technosaurus

sanapala mohanarao
  • 321
  • 1
  • 2
  • 16
matt.nguyen
  • 396
  • 2
  • 5
  • just needs checks at the end `[ ! "$PASSWORD" ] && usage` #and similar for other mandatory arguments – technosaurus Feb 21 '13 at 03:01
  • @technosaurus AFAICS that check is already there: `while [ "$1" != "" ] ...` – just somebody Feb 21 '13 at 17:10
  • this would still work `Script q q q q q q q q q q q q q` and none of the required values would be set – technosaurus Feb 21 '13 at 18:42
  • @technosaurus correct on both of your comments. I've updated the script accordingly (I misread the original question and only thought about parsing in the first place.) :) – matt.nguyen Feb 22 '13 at 16:59
  • @matt.nguyen i didn't test, but shouldn't = be == or -eq ? (I forget which is which string/number) ... but to test if a variable is set I usually do simply `[ "$VAR" ] || usage` ... if a variable is optional but needs to be set to _something_ you can use ${VAR:-default value} ... my guess is that _could_ be the case for some of these – technosaurus Feb 22 '13 at 22:06
  • @technosaurus See (http://stackoverflow.com/questions/3265803/bash-string-equality) :). I chose to be more verbose because I felt that it would be more helpful to the OP (I may be mistaken on that point). – matt.nguyen Feb 23 '13 at 23:43
1

getopts is bitching for a good reason. you should change your script's interface to conform to what people expect.

alternatively, you could use getopts twice, first for the pre-query options, shift, then for the rest.

just somebody
  • 18,602
  • 6
  • 51
  • 60
1

try this out

usage()
{
   echo "$0 -s <server> -i <instance> -u <user> -p <password> <query> -w <warning value> -c <critical value>"
}

for i in {0..12}
do
    arg=`expr $i +1`
    test ! "${!arg}" && usage && break
done

hope this helps

Balram
  • 21
  • 2
0

Well, a very caveman like way would be like this

usage ()
{
  echo 'Usage : Script -s <server> -i <instance> -u <user> -p <password>'
  echo '                  <query> -w <warning value> -c <critical value>'
  exit
}

[ ${13} ] || usage
Zombo
  • 1
  • 62
  • 391
  • 407
  • Thanks.. Now i get incase if user wont give 13 parameters while executing. But in addition, i do get an ugly error messages like "line 76: [: 21: unary operator expected" as these are mandatory .. How can i escape from this ?? – San Feb 20 '13 at 09:20
0

This is a non-standard approach, but one that I find very useful. Instead of passing values as arguments to specific flags (which is fairly annoying; the user should not be required to specify every value but reasonable defaults should be supplied), you can simply pass them directly via the environment, so that a typical call would look like:

SERVER=blah INSTANCE=foo Script 

It would be nice if you used lower case variable name so the user doesn't have to shout. This allows the script so simply avoid parsing the command line completely, as the values of the variables will be set when the script begins.

William Pursell
  • 204,365
  • 48
  • 270
  • 300