LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   script to send mail when raid fails (https://www.linuxquestions.org/questions/linux-newbie-8/script-to-send-mail-when-raid-fails-929494/)

niharikaananth 02-15-2012 10:20 AM

script to send mail when raid fails
 
Hi..All,
I have configured RAID1(software raid). And since I am newbie in shell scripting, I need shell script to send mail when any of the raid array get fails. It would be very appreciated if anybody already having the script and post it here. or please help me, how can I cut "[" "]" from the below command's output. The raid status is stored in mdstat file.
Code:

[ananth@localhost ~]$ cat mdstat | grep "blocks" | awk '{print $4'}
[UU]
[UU]
[UU]
[UU]
[UU]
[UU]

I'll expect the output as only UU instead of [UU].

MensaWater 02-15-2012 11:43 AM

First:
You don't need to cat AND grep - grep can read by itself - you just do:
Code:

grep "blocks" /proc/mdstat
Second awk by default uses white space (spaces/tabs etc...) for field delimiter so $4 would be the fourth field. Since there is no white space betwee "[" "UU" and "]" it is all considered one field.

You could try solving it by changing the delimiter twice assuming that "[" and "]" appear only once in the output:
Code:

grep "blocks" /proc/mdstat |awk -F[ '{print $2}' |awk -F] '{print $1}'
Notice your field is now $2 in the first awk because it is no longer delimited by white space and the "UU]" is the second thing after the "[" delimiter. Similarly in the second awk the field is $1 because "UU" is the first thing before the "]" delimiter.

You could perhaps simplify the above by using sed the command rather than dual awks.

cbtshare 02-15-2012 04:32 PM

Quote:

sed 's/^.*\(UU\).*$/\1/'
This one liner works.

niharikaananth 02-15-2012 08:52 PM

Thanks MensaWater
Sorry, I think I confused you by grep and print the output from only mdstat file instead /proc/mdstat file.
Code:

$grep "blocks" /proc/mdstat |awk -F[ '{print $2}' |awk -F] '{print $1}'
2/2
2/2
2/2
2/2
2/2
2/2

Since It was not giving output as "UU", I edited as below
Code:

$grep "blocks" /proc/mdstat |awk -F[ '{print $3}' |awk -F] '{print $1}'
UU
UU
UU
UU
UU
UU

Super, This is what I had expected from you. Here is the script, still giving the error but saying RAID OKAY.
Code:

$cat RAID
#!/bin/bash
status=( $(grep "blocks" /proc/mdstat |awk -F[ '{print $3}' |awk -F] '{print $1}' ) )
if [ "${!status[@]}" -ne "UU" ]; then
echo RAID FAILED!!!
else
echo RAID OKAY.
fi

Code:

$bash RAID
RAID: line 3: [: too many arguments
RAID OKAY.

Please help me that how can I get rid this error.

niharikaananth 02-15-2012 09:08 PM

Thanks cbtshare,
Code:

$grep "blocks" /proc/mdstat | awk '{print $4'} | sed 's/^.*\(UU\).*$/\1/'
UU
UU
UU
UU
UU
UU

Super working fine.

niharikaananth 02-16-2012 10:41 AM

Quote:

Originally Posted by niharikaananth (Post 4603594)
Thanks cbtshare,
Code:

$grep "blocks" /proc/mdstat | awk '{print $4'} | sed 's/^.*\(UU\).*$/\1/'
UU
UU
UU
UU
UU
UU

Super working fine.

Hi..Masters,
Here is a small script, still I am unable to ignore the errors.
Code:

cat check_raid_array
#!/bin/bash
status=( $(grep "blocks" /proc/mdstat | awk '{print $4'} | sed 's/^.*\(UU\).*$/\1/' ) )
if [ ${status[i]} -ne "UU" ]; then
echo RAID FAILED
else
echo RAID OKAY
fi

If I run the script I am getting the error as below.
Code:

bash check_raid_array
check_raid_array: line 3: [: UU: integer expression expected
RAID OKAY

Please help me to correct my mistakes.

catkin 02-16-2012 10:48 AM

-ne is a numeric comparison operator. You want the string comparison operator !=

niharikaananth 02-16-2012 12:00 PM

Quote:

Originally Posted by catkin (Post 4604200)
-ne is a numeric comparison operator. You want the string comparison operator !=

Thanks catkin,
Code:

#!/bin/bash
status=( $(grep "blocks" /proc/mdstat | awk '{print $4'} | sed 's/^.*\(UU\).*$/\1/' ) )
if [ "${status[i]}" != "UU" ]; then
echo RAID FAILED
else
echo RAID OKAY
fi

Code:

[root@localhost ananth]#bash check_raid_array
RAID OKAY
[root@localhost ananth]#echo $?
0

Working fine, But it is not showing as RAID FAILED while $status is U_ or UF or only U in any of the raid array. For example cat /proc/mdstat output is saved in a file and changed the md4 status from "UU" to "U_", Please see the below example
Code:

[root@localhost ananth]# cat mdstat
Personalities : [raid1]
md0 : active raid1 sdb1[1] sda1[0]
      513984 blocks [2/2] [UU]
     
md2 : active raid1 sdb3[1] sda3[0]
      2096384 blocks [2/2] [UU]
     
md3 : active raid1 sdb5[1] sda5[0]
      1469824 blocks [2/2] [UU]
     
md4 : active raid1 sdb6[1] sda6[0]
      497856 blocks [2/2] [U_]
     
md5 : active raid1 sdd1[1] sdc1[0]
      20964672 blocks [2/2] [UU]
     
md1 : active raid1 sdb2[1] sda2[0]
      15358016 blocks [2/2] [UU]

And also modified the script to grep "blocks" from mdstat file instead of /proc/mdstat.
Code:

#!/bin/bash
status=( $(grep "blocks" mdstat | awk '{print $4'} | sed 's/^.*\(UU\).*$/\1/' ) )
if [ "${status[i]}" != "UU" ]; then
echo RAID FAILED
else
echo RAID OKAY
fi

But if I run the script, still it is showing as "RAID OKAY" instead of RAID FAILED, which means I think it is reading only md0 and not reading other md devices.
Code:

[root@localhost ananth]# bash check_raid_array
RAID OKAY

Please help me that what can be done, to read every raid array result.

cbtshare 02-16-2012 02:18 PM

because the
Quote:

if [ "${status[i]}" != "UU" ]; then
line makes no-sense really.I guess you wanna put the contents in an array and the the cycle through it ,but i doesn't increase.you'd have to let "i =+ 1" , but I'd use a while loop with the nested If.

niharikaananth 02-16-2012 07:32 PM

Thanks cbtshare,
Since I am newbie in shell scripting I am unable to modify the script with "let". So could you please post the modified script with while loop.

chrism01 02-16-2012 08:09 PM

Assuming the grep awk line does what I think ie return status values like UU, U_ etc, how about something like
Code:

#!/bin/bash
for status in $(grep "blocks" mdstat | awk '{print $4'} | sed 's/^.*\(UU\).*$/\1/' )
do
    if [[ "$status" != "UU" ]]
    then
        echo RAID FAILED
    else
        echo RAID OKAY
    fi
done

For more sophistication, you'd also pull out the mdX values, so you know which one has failed;
not strictly reqd, but nice to have.

BTW, here are some good bash links
http://rute.2038bug.com/index.html.gz
http://tldp.org/LDP/Bash-Beginners-G...tml/index.html
http://www.tldp.org/LDP/abs/html/

cbtshare 02-16-2012 09:54 PM

chrism01's code does it , try that :)

niharikaananth 02-22-2012 09:14 AM

Thank you very much chrism01,
Sorry for the late response. Could you please help me to print failed devices using awk/sed? For example
Code:

cat mdstat
RAID status
Personalities : [raid1]
md0 : active raid1 sdb1[1] sda1[0]
      1020032 blocks [2/2] [__]
     
md2 : active raid1 sdb3[1] sda3[0]
      20482752 blocks [2/2] [UU]
     
md3 : active raid1 sdb5[1] sda5[0]
      537117056 blocks [2/2] [UF]
     
md4 : active raid1 sdb6[1] sda6[0]
      315741376 blocks [2/2] [UU]
     
md5 : active raid1 sdd1[1] sdc1[0]
      976759936 blocks [2/2] [_U]
     
md1 : active raid1 sdb2[1] sda2[0]
      102398208 blocks [2/2] [U_]
     
unused devices: <none>

Here I want to print out only failed devices which are in red color. So it would be appreciated if you post the awk or sed commands to print only failed device and by excluding those raid array which are good i.e UU.


All times are GMT -5. The time now is 03:43 PM.