1

I have a share backup bash script that works as is, but it uses several lines to do something that can be looped (I'm hoping). I'm thinking it can be much better, and the first step, in my mind, would be to use a loop to cycle through the shares.

In it scurrent state, the script I have calls three bash functions and a python script (that sends email with stderr and stdout) for each share, of which there are several (4 now, and maybe up to 6-8), and it looks like this:

create_log_dir "$share1_backup"
create_log "$share1_backup" "$log_file"
create_rsync_cmd "$log_file"

python backup.py $email_address \
"$rsync_command $rsync_args $share1 $share1_backup"

So the code above would be something like 20-30 lines for all the shares. I was hoping to make a loop that goes through these steps for each share that looks something like this (pseudocode-like example):

for var in list (each $share_var and $log_var)
do
  create_log_dir "$share_var"
  create_log "$share_var" "$log_var"
  create_rsync_cmd "$log_var"
done

I tried this format with some bash options and couldn't get it to work. Still new to bash, so I'm hoping to pick up some cool tips with this one.

Thanks in advance.

UPDATE EDIT

Here are the path and log variables and the for loop I'm using:

#variables
share1="/path/to/share/"
share1_backup="/path/to/share/backup"

# log creation
# If the 'rsync_logs' directory in destination doesn't exist, create it.
create_log_dir()
{
   backup_dest=$1
   if [ ! -d "$backup_dest/rsync_logs" ]
   then
      mkdir $backup_dest/rsync_logs
   fi
}

# Check for log_file existence; append '_alt' if exists.
create_log()
{
   backup_dest=$1
   log_file=$2
   log_file="$backup_dest/rsync_logs/$(date +"%Y-%m%d")_rsync_output.log"
   if [ -f $log_file ]
   then
      log_file="${log_file}_alt"
   fi
}

#loop
for pair in "share1_backup log_file"
do
  set -- $pair
  share=$1
  log=$2

  create_log_dir "$share"
  create_log "$share" "$log"
  create_rsync_cmd "$log"
done

So I tried it with the original answer:

for pair in "share1_backup log_file"

and... with the variable method (neither seemed to work - first one gave error because the directory, share1_backup/rsync_logs didn't exist - it didn't use the variable):

for pair in "${share1_backup} ${log_file}"

This second one resulted in empty log file.

UPDATE EDIT 2

I think the better approach to this, so that the two answers below will both work, is to build the logs somewhere else. I originally thought it'd be nice to save them in the backup destination, but then again, it might be good to save the logs on the machine on which all the shares are mounted, for consistency. Then I can write a script that copies them over periodically, if I must have them on the destination drives. This way, I can build the log_file variable ahead of time, and then use it in the loop, as David K. Hess pointed out.

Thanks again.

4
  • what are you using as list? Commented Dec 11, 2011 at 19:04
  • Well, the list would be my list of shares and the log variable. But it doesn't have to be a list, I guess. Not really certain if this is the best way or not??? Commented Dec 11, 2011 at 19:12
  • In your latest script, in the first case with the literals, it is going to use those exact values as arguments to your functions (which is not what I think you want). In the second case, you aren't initializing the "log_file" variable before the for loop executes. Commented Dec 11, 2011 at 21:57
  • Yah, I see what you mean... Based on this, it seems this idea may not work after all; or, at least, not like I envisioned it. I think I need to fiddle with some other ideas. Thanks a lot for all your help. Commented Dec 11, 2011 at 22:06

2 Answers 2

3

This approach should work as long as your paths don't have spaces in them:

for pair in "share1_var log1_var" "share2_var log2_var"
do
    set -- $pair
    share_var = $1
    log_var = $2
    create_log_dir "$share_var"
    create_log "$share_var" "$log_var"
    create_rsync_cmd "$log_var"
done
Sign up to request clarification or add additional context in comments.

6 Comments

I'm thinking of trying this as a function. In this case, I would call something like run_functions "$share_name" "$log_name".$share_name would be arg 1 and $log_name arg 2. Would this still work? I'm unfamiliar with the pair concept, although it seems straight forward.
I think a function approach is orthogonal to your basic dilemma - you need to iterate over a list where each item consists of another two items. So, you still have the issue of looping with two variables in order to make your function call. Of course, this is all very simple in Python so you might want to look at the subprocess module and just execute your commands from Python.
Yes, after fiddling with it a bit, I realized that I was chicken and egging it a bit. Originally, this bash script was supposed to simply be a container to run the python script. Now that you mention it, though, adding some of this logic to the python program or building another to do this might be the better approach. Thanks for the advice.
David K. Hess: I'm having trouble with your solution. The line for pair in "share1_var log1_var" seems like it should work... I need it to use variables that were declared above as paths. So I tried for pair in "${share1} ${log1_var}" and my log file ends up empty.
Hard to tell - can you update your question with the latest version of your script?
|
2

What about using an array? It works even if your values contain spaces.

array=("share1" "log1"
       "share2" "log2")
for ((i=0; i<${#array[@]}; i+=2)) ; do
    share_var=${array[i]}
    log_var=${array[i+1]}
    create_log_dir "$share_var"
    create_log "$share_var" "$log_var"
    create_rsync_cmd "$log_var"
done

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.