LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   using getopts with flags to backup cronjobs (https://www.linuxquestions.org/questions/linux-newbie-8/using-getopts-with-flags-to-backup-cronjobs-4175582767/)

linuxnewbie0101 06-21-2016 01:14 PM

using getopts with flags to backup cronjobs
 
Hi, i am new to this forum so please let me know if i post in the wrong place.

I was tasked to create a script so we can backup cronjobs on the server.

suggested syntax:
./script_name.sh -m backup -p /path/to/backup/dir

m = method = backup or restore
p = path to backup or to restore to
u = (optional) jobs by user

i created the script, however, it is not working as expected and i continue to get the following error:
./getops_local.sh -m backup -p /home/test/backup
./getops_local.sh: line 55: syntax error near unexpected token `;;'
./getops_local.sh: line 55: ` ;;'


can anyone take a look and see if you can point me to the right direction?


below is the script that i created

Code:

#!/bin/bash

#bkuplocation="backups/$hostname"
bkuplocation="/systems/homes/cronjobs_bk/$hostname"

#Help function
function HELP {
  echo " Command line switches -m & -p are required, -u is optional."
  echo " -m  --Sets the value for option to backup or restore (backup/restore)."
  echo " -p  --Sets the path to backup from and restore to."
  echo " -u  --(OPTIONAL) Sets the user jobs to backup."
  echo " -h  --Displays this help message. No further functions are performed."\\n
  exit 1
}

#Check the number of arguments. If none are passed, print help and exit.
NUMARGS=$#
if [ $NUMARGS -eq 0 ]; then
  HELP
fi

### Start getopts code ###

while getopts :m:p:u?h? OPTIONS; do
  case $OPTIONS in
    m)
      method=$OPTARG
      ;;

    p)
      location=$OPTARG
      ;;

    u)
      user=$OPTARG
      ;;

    h) HELP
      ;;

  \?) echo -e "Option $OPTARG not allowed."
      HELP
      #echo -e "Use -h to see the help documentation."
      #exit 2
      ;;
  esac
done

case $method in
  backup)
    if [$method = 'backup'] && if [$user ==""]; then
      cp "$location/*" "${bkuplocation}/$hostname";
    else
      cp "$location/$user" ${bkuplocation};
    fi
  ;;

  restore)
    if [$method = 'restore'] && if [$user ==""]; then
      cp "${bkuplocation}/$hostname/*" ${location};
    else
      cp "${bkuplocation}/$hostname/$user" ${location};
    fi
  ;;
  esac
done

shift $((OPTIND-1))

exit 0


suicidaleggroll 06-21-2016 01:23 PM

Please put the code in [code][/code] tags to preserve formatting and prevent characters from being replaced by smiley faces.

linuxnewbie0101 06-21-2016 01:26 PM

TY for the tip.

suicidaleggroll 06-21-2016 01:36 PM

The problem with the ";;" error is your if statements. They should look more like this:
Code:

if [ $method == 'backup' ] && [ $user == "" ]; then
Note the spaces around the brackets and equal signs, and you have an extra "if" in there.

linuxnewbie0101 06-21-2016 02:21 PM

Quote:

Originally Posted by suicidaleggroll (Post 5564302)
The problem with the ";;" error is your if statements. They should look more like this:
Code:

if [ $method == 'backup' ] && [ $user == "" ]; then
Note the spaces around the brackets and equal signs, and you have an extra "if" in there.

Thank you for the quick response and keen eyes. yes this did resolve the immediate issue, however, i am now receiving the following error with changes for testing purpose,

bkuplocation="/tmp/test2/$hostname"

and the syntax i used to call is ./getops_local.sh -m backup -p /tmp/test

jfang@jfang-T530:~/test$ ./getops_local.sh -m backup -p /tmp/test
cp: cannot stat ‘/tmp/test/*’: No such file or directory

TY for all your help

suicidaleggroll 06-21-2016 02:35 PM

Looks like the files you're telling it to back up (/tmp/test/*) don't exist, so it's complaining when it tries to copy them to the backup location. It's not an error per-se, but if you want it to do something other than yell at the user for providing a location with no files you'll need to test for that case explicitly and do something special.

linuxnewbie0101 06-21-2016 03:15 PM

implemented crontab to do some work.

Code:

#!/bin/bash

bkuplocation="/systems/homes/cronjobs_bk/$hostname"

#Help function
function show_help {
  echo " Command line switches -m & -p are required, -u is optional."
  echo " -m  --Sets the value for option to backup or restore (backup/restore)."
  echo " -p  --Sets the path to backup from and restore to."
  echo " -u  --(OPTIONAL) Sets the user jobs to backup."
  echo " -h  --Displays this help message. No further functions are performed."
  exit 1
}

#Check the number of arguments. If none are passed, print help and exit.
numargs=$#
if [ $numargs -eq 0 ]; then
  show_help
fi

# Start getopts code

while getopts :m:p:u?h? options; do
  case $options in
    m)
      method=$optarg
      ;;
    p)
      location=$optarg
      ;;
    u)
      user=$optarg
      ;;
    h) show_help
      ;;
  \?) echo -e "Option $optarg not allowed."
      show_help
      #echo -e "Use -h to see the help documentation."
      #exit 2
      ;;
  esac
done

case $method in
  backup)
    if [ $method == 'backup' ] && [ $user =="" ]; then
      for i in "/var/spool/cron/crontabs/*"; do
        crontab -l -u $i > "${bkuplocation}/$hostname/";
      done
    else
      crontab -l -u $user > "${bkuplocation}/$hostname/";
    fi
    ;;
  restore)
    if [ $method == 'restore' ] && [ $user =="" ]; then
      for i in "${bkuplocation}/$hostname/*"; do
        crontab $i;
      done 
    else
        crontab $user < "${bkuplocation}/$hostname/$user";
    fi
    ;;
esac
shift $((OPTIND-1))

exit 0


any thoughts and feedbacks?

keefaz 06-21-2016 04:10 PM

You could add an usage function with just one line resuming program invokation, like
Code:

Usage:
    program_name [-m -p -u -h]

Maybe, add an exit number parameter to the help function, this way when one wants to just see the help page, the program doesn't exit with error (1)

Don't see the relevance of shift $((OPTIND-1)) just before exit 0 there...

[edit]
I think you forget filenames for cron backups files here:
Code:

if [ $method == 'backup' ] && [ $user =="" ]; then
      for i in "/var/spool/cron/crontabs/*"; do
        crontab -l -u $i > "${bkuplocation}/$hostname/";
      done
    else
      crontab -l -u $user > "${bkuplocation}/$hostname/";
    fi


linuxnewbie0101 06-22-2016 08:56 AM

update the script for review, for some reason the script completed without errors. but it didnt do anything.

also the bkuplocation is also a nas drive on the network.

Please help.
Code:

#!/bin/bash

bkuplocation="/systems/homes/cronjobs_bk/$host"
cron_srouce="/var/spool/cron/crontabs/*"

#Help function
function show_help {
  echo " Command line switches -m & -p are required, -u is optional."
  echo " -m  --Sets the value for option to backup or restore (backup/restore)."
  echo " -p  --Sets the path to backup from and restore to."
  echo " -u  --(OPTIONAL) Sets the user jobs to backup."
  echo " -h  --Displays this help message. No further functions are performed."
  exit 1
}

#Check the number of arguments. If none are passed, print help and exit.
numargs=$#
if [ $numargs -eq 0 ]; then
  show_help
fi

# Start getopts code
while getopts :m:p?u?h? options; do
  case $options in
    m)
      method=$optarg
      ;;
    p)
      location=$optarg
      ;;
    u)
      user=$optarg
      ;;
    h) show_help
      ;;
  \?) echo -e "Option $optarg not allowed."
      show_help
      ;;
  esac
done

shift $((OPTIND-1))

case $method in
  backup)
    if [ ! -d $bkuplocation ]; then
        mkdir $bkuplocation
    fi
    if [ -z $location ] && [ -z $user ]; then
      for i in $cron_srouce; do
        crontab -l -u $i > "$bkuplocation";
      done
    elif [ ! -z $location ] && [ ! -z $user ]; then
      for i in $cron_srouce; do
        crontab -l -u $i > "$location";
      done
    elif [ -z $location ] && [ ! -z $user ]; then
      for i in $cron_srouce; do
        crontab -l -u $user > "$bkuplocation";
      done
    elif [ ! -z $location ] && [ -z $user ]; then
      crontab -l -u $i > "$location";
    else show_help
    fi
  ;;

  restore)
    if [ ! -d $bkuplocation ]; then
        echo "no backup found for $host"
    fi
    if [ -z $location ] && [ -z $user ]; then
      for i in $bkuplocation; do
        crontab $i;
      done 
    elif [ ! -z $location ] && [ ! -z $user ]; then
      for i in $location; do
        crontab -l -u $user < $location;
      done
    elif [ ! -z $location ] && [ -z $user ]; then
      for i in $location; do
        crontab -l -u $i < $location;
      done
    elif [ -z $location ] && [ ! -z $user ]; then
      crontab -l -u $user < "$bkuplocation/*";
    else
      show_help
    fi
  ;;
esac

shift $((OPTIND-1))

exit 0


suicidaleggroll 06-22-2016 09:17 AM

How do you know it completed without errors and how do you know it didn't do anything?
Was this running in cron or did you run it yourself?

I suggest you take a step back from the script and just focus on the crux of what it's doing, because even ignoring the numerous logic errors in your if/elif blocks and for loops, neither the backup nor restore portions of your script are correct. Pick one example, eg:
Code:

crontab -l -u $user > "$location";
and
Code:

crontab -l -u $user < $location;
What is $user and what is $location? Pick an example value for each, and actually run those commands, neither of them will work correctly. Your backup is trying to dump text to a directory, which you can't do, and you can't pipe text into the stdin of "crontab -l" and expect it to do anything. You need to figure out how to tackle the actual function of the script before you can wrap it in if statements and for loops to do something useful.

Once you've tackled the actual backup/restore commands, you need to take a hard look at your if/elif blocks and for loops, because there are many problems there, eg:
1)
Code:

elif [ ! -z $location ] && [ -z $user ]; then
  crontab -l -u $i > "$location";

There is no for loop, therefore $i is undefined. I assume you meant $user.

2)
Code:

elif [ ! -z $location ] && [ ! -z $user ]; then
  for i in $cron_srouce; do
    crontab -l -u $i > "$location";
  done

Why are you looping over $cron_srouce (which is misspelled btw) when they provided a user?

3)
Code:

if [ -z $location ] && [ -z $user ]; then
  for i in $bkuplocation; do
    crontab $i;
  done

What is that supposed to do?


Also, bash does not require semi-colons at the end of lines like C does. You have that all over the place in the script, and while it won't hurt anything, it's unnecessary and the usage is inconsistent, which makes things look messy.

keefaz 06-22-2016 09:19 AM

Output files still missing, I am surprised no error raise on output when the script tries to redirect stdout in a directory

[edit]
Yes as suicidaleggroll said :)
Code:

if [ -z $location ] && [ -z $user ]; then
      for i in $cron_srouce; do
        crontab -l -u $i > "$bkuplocation";
      done
    elif [ ! -z $location ] && [ ! -z $user ]; then
      for i in $cron_srouce; do
        crontab -l -u $i > "$location";
      done
    elif [ -z $location ] && [ ! -z $user ]; then
      for i in $cron_srouce; do
        crontab -l -u $user > "$bkuplocation";
      done
    elif [ ! -z $location ] && [ -z $user ]; then
      crontab -l -u $i > "$location";
    else show_help
    fi


linuxnewbie0101 06-22-2016 09:28 AM

the script was suppose to backup or restore for all or specific user.
bkuplocation is the designated location, however, -p can introduce new path location to backup and restore.

i ran the script and no errors, i checked the bkuplocation and was not able to see any files.

TY

michaelk 06-22-2016 09:51 AM

In addition

Is the NAS mounted by default?

Quote:

bkuplocation="/systems/homes/cronjobs_bk/$host"
$host is not defined.

[ -z string ] means true if string is blank. As stated go back and make sure your conditionals match your cases.

To simplify a bit don't use different variable names for the backup location.

linuxnewbie0101 06-22-2016 10:02 AM

Quote:

Originally Posted by michaelk (Post 5564688)
In addition

Is the NAS mounted by default?


$host is not defined.

[ -z string ] means true if string is blank. As stated go back and make sure your conditionals match your cases.

To simplify a bit don't use different variable names for the backup location.



yes the NAS is mounted by default,
$host is suppose to be $hostname as a directory of hostname
-z string does mean the string is blank blank as in optional flag.

TY

linuxnewbie0101 06-22-2016 10:03 AM

updated script

Code:


#!/bin/bash

bkuplocation="/systems/homes/cronjobs_bk/$hostname"
cron_srouce="/var/spool/cron/crontabs/*"
hostname=$(hostname -s)

#Help function
function show_help {
  echo " Command line switches -m is required, -p & -u are optional."
  echo " -m  --Sets the value for option to backup or restore (backup/restore)."
  echo " -p  --(OPTIONAL) Sets the path to backup from and restore to."
  echo " -u  --(OPTIONAL) Sets the user jobs to backup."
  echo " -h  --Displays this help message. No further functions are performed."
  exit 1
}

#Check the number of arguments. If none are passed, print help and exit.
numargs=$#
if [ $numargs -eq 0 ]; then
  show_help
fi

# Start getopts code
while getopts :m:p?u?h? options; do
  case $options in
    m)
      method=$optarg
      ;;
    p)
      location=$optarg
      ;;
    u)
      user=$optarg
      ;;
    h) show_help
      ;;
  \?) echo -e "Option $optarg not allowed."
      show_help
      ;;
  esac
done

shift $((OPTIND-1))

case $method in
  backup)
    if [ ! -d $bkuplocation ]; then
        mkdir $bkuplocation
    fi
    if [ -z $location ] && [ -z $user ]; then
      for i in $cron_srouce; do
        crontab -l -u $i > "$bkuplocation/$i"
      done
    elif [ ! -z $location ] && [ ! -z $user ]; then
      for i in $cron_srouce; do
        crontab -l -u $user > "$location/$user"
      done
    elif [ -z $location ] && [ ! -z $user ]; then
      for i in $cron_srouce; do
        crontab -l -u $user > "$bkuplocation/$user"
      done
    elif [ ! -z $location ] && [ -z $user ]; then
      for i in $cron_srouce; do
        crontab -l -u $i > "$location/$i"
    else
      show_help
    fi
  ;;

  restore)
    if [ ! -d $bkuplocation ]; then
        echo "no backup found for $host"
    fi
    if [ -z $location ] && [ -z $user ]; then
      for i in $bkuplocation; do
        crontab $i
      done 
    elif [ ! -z $location ] && [ ! -z $user ]; then
      for i in $location; do
        crontab $user < "$location/$user"
      done
    elif [ ! -z $location ] && [ -z $user ]; then
      for i in $location; do
        crontab $i < $location
      done
    elif [ -z $location ] && [ ! -z $user ]; then
      for i in $bkuplocation; do
        crontab $user < "$bkuplocation/$user"
    else
      show_help
    fi
  ;;
esac

shift $((OPTIND-1))

exit 0



All times are GMT -5. The time now is 10:12 AM.