LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   script to send an email (https://www.linuxquestions.org/questions/linux-newbie-8/script-to-send-an-email-902985/)

linuxandtsm 09-14-2011 10:02 AM

script to send an email
 
Hi all,

I have a bash script to send alert email if disk usage exceeds 90%. This works fine but this sends one email for each of filesystem that exceeds 90%. I want to send only one email listing all filesystems with over 90% usage. How to change this script. Thanks in advance!

Code:

#!/bin/sh
df -Ph |awk '{ print $5 " " $1 " " $6 }' | while read outstring;
do
  percentuse=$(echo $outstring | awk '{ print $1}' | cut -d'%' -f1  )
  partition=$(echo $outstring | awk '{ print $2 }' )
  mountedon=$(echo $outstring | awk '{ print $3 }' )

  if [ $percentuse -ge 90 ]; then
    echo "Filesystem near fill-up |
    mail -s "disk space is low \"$mountedon\" " me@email.com
  fi
done


doru 09-14-2011 10:19 AM

Maybe this one:
Code:

#!/bin/sh
df -Ph |awk '{ print $5 " " $1 " " $6 }' | while read outstring;
do
  percentuse=$(echo $outstring | awk '{ print $1}' | cut -d'%' -f1  )
  partition=$(echo $outstring | awk '{ print $2 }' )
  mountedon1=$(echo $outstring | awk '{ print $3 }' )

  if [ $percentuse -ge 90 ]; then
    mountedon=$mountedon\ $mountedon1
  fi
done

echo "Filesystem near fill-up |
    mail -s "disk space is low \"$mountedon\" " me@email.com


druuna 09-14-2011 10:46 AM

Hi,

@doru: I don't think that $mountedon is still set outside the while read loop.

Something like this should work if the while read loop is used:
Code:

#!/bin/sh

LOG="/tmp/script.log"

df -Ph | awk '{ print $5 " " $1 " " $6 }' | while read outstring;
do
  percentuse=$(echo $outstring | awk '{ print $1}' | cut -d'%' -f1  )
  partition=$(echo $outstring | awk '{ print $2 }' )
  mountedon=$(echo $outstring | awk '{ print $3 }' )

  if [[ $percentuse -ge 90 ]]; then
    echo "Filesystem near fill-up : $mountedon" >> $LOG
  fi
done

[[ -a $LOG ]] && mail -s "disk space is low" me@email.com < $LOG && rm $LOG

Hope this helps.

linuxandtsm 09-14-2011 10:57 AM

Hi druuna,

Thanks for the quick reply.
I got this error.

./diskusage.sh: line 18: [[-a: command not found

druuna 09-14-2011 11:07 AM

Hi,
Quote:

Originally Posted by linuxandtsm (Post 4471514)
Thanks for the quick reply.

You're welcome :)

Quote:

I got this error.

./diskusage.sh: line 18: [[-a: command not found
You seem to be missing a space between [[ and -a.

Hope this helps.

linuxandtsm 09-14-2011 01:48 PM

Hi druuna,

works perfect and is there any way to make text in the email to be bold.
For example if i want to highlight the name of the filesystem in the text.

And could you please explain what
Code:

[[ -a $LOG ]]
is doing
and also where can i read more about these.
Thank you!

druuna 09-14-2011 03:24 PM

Hi,
Quote:

Originally Posted by linuxandtsm (Post 4471652)
And is there any way to make text in the email to be bold.
For example if i want to highlight the name of the filesystem in the text.

The message that is send is plain text and to my knowledge you cannot apply layout to plain text.

However, it should be possible to create and send a mail in HTML layout.

I don't have any bash experience doing that. Maybe another LQ member can help you with that.

Quote:

[[ -a $LOG ]]
The -a option checks if a file is present. This:
Code:

[[ -a $LOG ]] && mail -s.....
Checks to see if the log file is present and if so (the &&) execute the mail command.

druuna 09-14-2011 03:32 PM

Hi,

Some bash tutorials:

- Bash Guide for Beginners
- Advanced Bash-Scripting Guide
- BASH Frequently Asked Questions

Sed/Awk

- gnu sed
- gnu awk

Hope this helps.

Reuti 09-15-2011 08:44 AM

As a small variation of druunaís script, you can also pipe all to the mail command in case you use a subshell and avoid a temporary file:
Code:

#!/bin/sh

(

unset FILLING

df -Ph | awk '{ print $5 " " $1 " " $6 }' | while read outstring;
do
  percentuse=$(echo $outstring | awk '{ print $1}' | cut -d'%' -f1  )
  partition=$(echo $outstring | awk '{ print $2 }' )
  mountedon=$(echo $outstring | awk '{ print $3 }' )

  if [[ $percentuse -ge 90 ]]; then
    FILLING=1
    echo "Filesystem near fill-up : $mountedon"
  fi
done

if [ -z "$FILLING" ]; then
    echo "All filesystem are in safe condition"
fi

) | mail -s "Daily disk space report" me@email.com

On the hand hand you can say that you want only mails in case a filesystem is filling up, but then you donít know whether the script didnít run last night for any reason or that there is no filesystem in question at all.

druuna 09-15-2011 09:03 AM

Hi Reuti,

As stated in post #3: Variables set inside the while read loop are not known outside that loop (FILLING in this case).

This part will always be printed in your script:
Code:

if [ -z "$FILLING" ]; then
    echo "All filesystem are in safe condition"

With a confusing output as a result:
Code:

Filesystem near fill-up : /data/Movie
Filesystem near fill-up : /data/Sounds
All filesystem are in safe condition


Reuti 09-15-2011 09:16 AM

Ouch, you are right of course. We would need to request the #!/bin/bash as shell in the script and put the selection at the end:
Code:

#!/bin/bash

(

unset FILLING

while read outstring;
do
  percentuse=$(echo $outstring | awk '{ print $1}' | cut -d'%' -f1  )
  partition=$(echo $outstring | awk '{ print $2 }' )
  mountedon=$(echo $outstring | awk '{ print $3 }' )

  if [[ $percentuse -ge 90 ]]; then
    FILLING=1
    echo "Filesystem near fill-up : $mountedon"
  fi
done < <(df -Ph | awk '{ print $5 " " $1 " " $6 }')

if [ -z "$FILLING" ]; then
    echo "All filesystem are in safe condition"
fi

) | mail -s "Daily disk space report" me@email.com


druuna 09-15-2011 09:19 AM

@Reuti: :) That works!

linuxandtsm 09-15-2011 09:31 AM

Hi druuna and Reuti,

Thank you both for helping me.

If i want to run this script daily as cron job, is it sufficient to put an entry in crontab via crontab -e or
should this script also be placed in /etc/cron.daily in RHEL5 ?

druuna 09-15-2011 09:35 AM

Hi,

You can use crontab -e (no root privileges are needed to run this script, so use a normal user).

An entry like this should work (run script daily at 01:05):
Code:

05 01 * * * /full/path/to/diskusage.sh
Hope this helps.

doru 09-15-2011 11:53 AM

Quote:

Originally Posted by druuna (Post 4471504)
Hi,

@doru: I don't think that $mountedon is still set outside the while read loop.

Yes it does. You need to use local within a function to get any sort of encapsulation in bash. And in sh, too, druuna.

My script needs two improvements:
1. It sends an email no matter what. mountedon should be tested before sending mail.
2. It sends all valuable information in subject. It should be placed in the message body.


All times are GMT -5. The time now is 10:27 PM.