I am working on a a script that need to take two script arguments and use them as variables in the script. I couldn't get this working and unable to find out what I am doing wrong. I see the issue is the second argument, as I see in some of my tests(as mentioned in the bottom of this post) it is not being read.

Here is the code:


   echo ""
    echo "Usage: $0 -p patch_level -e environment"
    echo -e "\t-p Patch level that you are tryin to update the server"
    echo -e "\t-e Environment that the patch need to be run on"
   exit 1 # Exit script after printing help

while getopts "p:e" opt
   case "${opt}" in
      p ) patch_level="$OPTARG" ;;
      e ) _env="$OPTARG" ;;
      ? ) help ;;    # Print help in case parameter is non-existent


if [ -z "$patch_level" ] || [ -z "$_env" ];    # checking for null parameter
   echo "Some or all of the parameters are empty";
   echo "$patch_level and $_env"

When I run the script like below , I get this.

> ./restart.sh -p 2021 -e sbx 
>  Some or all of the parameters are empty
> Usage: ./restart.sh -p patch_level -e environment
>         -p Patch level that you are tryin to update the server
>         -e Environment that the patch need to be run on

Note: I modeled my code based on the third answer in this

How can I pass a command line argument into a shell script?

I see the issue is with the second variable (-e). Because if I change the last if statement from "or to and", the script runs but doesn't print anything for the second variable:

here is what I am talking about

if [ -z "$patch_level" ] && [ -z "$_env" ];

the output is

./restart.sh -p 2021 -e sbx
  2021 and
 This server will be patched to 2021

I am on Ubuntu if that matters.

1 Answer 1


$_env is unset due to how you pass arguments to getopts.

You need to add a colon after the e to tell getopts the option takes an argument.

while getopts "p:e:" op
              mandatory here


help getopts | less
  • Thanks much. I completely overlooked it. That helped . I know this is not part of the question but asking anyway. Is there a way , I can accept on certain strings for second argument. for example -e will only take sbx|inf|perf|prod
    – MO12
    Commented Jan 28 at 21:10
  • Thanks to post a new question Commented Jan 28 at 21:22
  • @MO12, most usually you'd just add another test later in the script, e.g. case $_env in sbx|inf|perf|prod) ;; *) exit 1;; esac
    – ilkkachu
    Commented Jan 29 at 16:00
  • @ilkkachu thank you
    – MO12
    Commented Jan 29 at 16:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .