How to send mail at specific calculated time interval?

Hi All,
I want to send an email if the time difference from previous mail sent is more than or equal to 30 mins.
I have written below code and it's working fine.
In this script I am storing previous mail sent time in txt file.
Instead of storing in txt file how to store in a variable.
Initially I am putting some date manually in the file prev_mail_sent.txt to assume initial mail sent.

Please help to implement this without creating any file use variable.

v_par=8
num_minutes=30
if [[ $v_par -eq 8 ]]; then
mail_date=`cat prev_mail_sent.txt`
curr_date=$(date +"%Y-%m-%d %H:%M:%S")
diff_sec=`echo "$(($(date -d "$curr_date" '+%s') - $(date -d "$mail_date" '+%s')))"`
d_min=`expr $diff_sec / 60`
if [[ $d_min -ge  $num_minutes ]]; then
mail -s "mail sent"
rm -f prev_mail_sent.txt
printf "$(date +"%Y-%m-%d %H:%M:%S")\n" > prev_mail_sent.txt
fi
fi

Thanks in advance.

You have quite a bit in there that is unnecessary. If you keep all date/times as seconds, it will make it a little easier:-

v_par=8
num_minutes=30

if [[ $v_par -eq 8 ]]; then
   read mail_date < prev_mail_sent.txt
   curr_date=$(date +%s)

   ((diff_sec=$curr_date - $mail_date) ))
   ((diff_min=$diff_sec / 60))

   if [[ $diff_min -ge  $num_minutes ]]; then
      mail -s "mail sent"                              # You probably should specify a target address and some content here
      rm -f prev_mail_sent.txt
      printf "$curr_date\n" > prev_mail_sent.txt
   fi

fi

Does that help a little? I've trimmed out unnecessary sub-processes cause by back-ticks ` , expr and the cat too. it might be marginal, but they (along with getting the current date once) should keep this a little more consistent.

Let us know if this suits your needs.

Kind regards,
Robin

Hi Robin,

Thanks for making the code simple.

My main concern is we are storing the previous email sent in a prev_mail_sent.txt file. Instead of that we have to store in some variable.
Could you please help me with that.

Thanks in advance.

Is your script going to loop forever? (presumably pausing so you don't murder the CPU)

If so, then you should simply assign the value of $curr_date to mail_date when you send a mail.

Rather than forgetting about it altogether, I would still write the file and move the line read mail_date < prev_mail_sent.txt to before the loop so that you read in a sensible starting value and if you script terminates for some reason (intentionally or otherwise) then when you start it up again, it will know where to pick up from.

An alternate to a loop might be to schedule the script every minute as a run-through-once process that stores the value in a file. If the script as a whole might take quite a while to run (depending on what other processing you are doing within it) then you might need to ensure you don't run it twice at the same time. There are various mechanisms for doing that if you need them. Let us know if you want help with these and I'm sure someone can work with you.

Robin

This is quite simple: at some point you have to create said text file:

some_process > /text/file

i.e.:

printf "%s\n" "This is the mail text." > /text/file

Now, instead of doing that, you put that output into a variable:

variable="$(some_process)"

When you change your script test what you have written first this way:

[...your script here...]

variable="$(some_process)"
echo 'mail-text =='$variable'=='

[...your script continued here...]

I hope this helps.

bakunin

Hi All,

I have tried the below code it's not working.It's sending mail every time when I have executed.

I have hard coded last_mail_date1 for initial comparison.After that once mail sent after 10 mins it has to update with current date.

v_par=8
num_minutes=10
if [[ $v_par -eq 8 ]]
then
last_mail_date1="2017-06-05 01:47:25"
last_mail_date=$last_mail_date1
curr_date=$(date +"%Y-%m-%d %H:%M:%S")
diff_sec=`echo "$(($(date -d "$curr_date" '+%s') - $(date -d "$last_mail_date" '+%s')))"`
diff_min=`expr $diff_sec / 60`
if [[ $diff_min -ge  $num_minutes ]]; then
mail -s "mail sent"
last_mail_date1=$(date +"%Y-%m-%d %H:%M:%S")
fi
fi 

Please help me.

Thanks in advance.

Can you run this with the following at/near the top and show us the output please?

set -x

It will better show us the script flow.

Kind regards,
Robin

gladly so: First, start by indenting your code. This will help you keep track of the branching. If you throw in some empty lines for better reading all the better:

v_par=8
num_minutes=10
if [[ $v_par -eq 8 ]] ; then
     last_mail_date1="2017-06-05 01:47:25"
     last_mail_date=$last_mail_date1
     curr_date=$(date +"%Y-%m-%d %H:%M:%S")
     diff_sec=`echo "$(($(date -d "$curr_date" '+%s') - $(date -d "$last_mail_date" '+%s')))"`
     diff_min=`expr $diff_sec / 60`

     if [[ $diff_min -ge  $num_minutes ]]; then
          mail -s "mail sent"
          last_mail_date1=$(date +"%Y-%m-%d %H:%M:%S")
     fi
fi 

Second: get rid of these backticks. They are really, positively, definitely OUTDATED sicne about 25 years or so and should not be used any more! The same is true for the ridiculuos expr -statement. Modern shells have learned to do integer artithmetic, so don't use an external program for something the shell can do it itself.

v_par=8
num_minutes=10
if [[ $v_par -eq 8 ]] ; then
     last_mail_date1="2017-06-05 01:47:25"
     last_mail_date=$last_mail_date1
     curr_date=$(date +"%Y-%m-%d %H:%M:%S")
     diff_sec=$(( $(date -d "$curr_date" '+%s') - $(date -d "$last_mail_date" '+%s') ))
     diff_min=$(( diff_sec / 60 ))

     if [[ $diff_min -ge  $num_minutes ]]; then
          mail -s "mail sent"
          last_mail_date1=$(date +"%Y-%m-%d %H:%M:%S")
     fi
fi 

But the real problem is perhaps:

1) You have no "file where the mail text is stored", at lease not in your script (which i suspect is not the read script but an arbitrary part thereof).

2) The mail-command is not sending any real mail, because the mail body is completely missing and so is the receiver.

I hope this helps.

bakunin