Just need to do some basic thing which I could manage on my own but turned out I have doubt on the result I get...
I need to produce a grand total using df command on specific filesystem on two different servers.
ssh server1 df -mP | egrep "/dev/md10|/dev/md11" | sort ; ssh server1 df -mP --total | grep "total" | egrep -v "/dev/md10|/dev/md11
The result:
/dev/md10 183004016 87303581 95700436 48% /si001c1
/dev/md11 183004016 165986430 17017587 91% /si001c2
total 366565396 253332843 113232554 70%
And then I used same command on the 2nd server to get the grand total. My question, the grand total I get seem not right (I'm not sure) and how to produce a grand total by combining both using same command in anyway using single line command or as a basic script in bash. Thanks for the help.
Update: This is an update after following the guide from @EdmCoff.
printf "Grand total: " ; (ssh server1 df -m /dev/md11 ; ssh server2 df -m /dev/md1*) | awk 'a+=$2;b+=$3;c+=$4;d+=$5/3} END {print a" "b" "c" "d%}'
Result:
Grand total: 549012050 501832399 47179652 92%
Built a script (re-done):
#!/bin/bash
(ssh server1 df -m --no-sync "/dev/md11" ; ssh server2 df -m --no-sync "/dev/md1*") | sed -e /^Filesystem/d | sort > df_udsall
#(cat df_udsall)
printf "\nUDS:\nserver1 & server2\n"
printf "Mounted on Free space Disk usage Use"%%" Disk state"
while read df_udsall
do
USAGE=$(echo $df_udsall ; echo $grand_total) | awk '{print $5}' | cut -d"%" -f1
if [[ "$USAGE" -ge " 95" ]]
then
STATUS='CRITICAL'
elif [[ "$USAGE" -ge " 90" ]]
then
STATUS='WARNING'
else
STATUS='OK'
fi
printf "$(echo $df_udsall | awk '{print $6, $4, $3, $5}' > df_udsall_stats)"
column -t df_udsall_stats | perl -ne 'chomp ; printf "\n%-18s %8s %12s %6s %-2s", split / +/' ; printf "`echo -ne $STATUS`"
done < df_udsall
printf "\n\nGrand total " ; cat df_udsall | awk '{b+=$4;c+=$3;d+=$5/3} END {print b" "c" "d "%"}' > grand_total
column -t grand_total | perl -ne 'chomp ; printf "%15s %12s %6s %-2s", split / +/' ; printf "`echo -ne $STATUS`"
rm -f df_udsall df_udsall_stats grand_total
The script above need some fine tuning.
Expected result:
UDS:
server1 & server2
Mounted on Free space Disk usage Use% Disk state
/sic1 16202762 166801255 92% WARNING
/sic2 15648157 167355860 92% WARNING
/sic3 15256569 167747448 92% WARNING
Grand total: 47107488 501904563 92% OK
Fixed tripleee script output result:
UDS:
server1 & server2
Mounted on Free space Disk usage Use% Disk state
/sic001c1 92146461 90857556 50% OK
/sic001c2 16873531 166130486 91% WARNING
/sic001c3 16832710 166171307 91% WARNING
/sic001c4 16362388 166641629 92% WARNING
Grand total: 142215090 589800978 81 OK%
Here is an attempt at refactoring your script into a version where Awk is wholly in control of the calculations and formatting of the output, as suggested in several comments. I have inlined comments which you might want to remove.
#!/bin/bash
# use a loop to reduce duplication of ssh options etc
while read -r server mounts; do
ssh "$server" df -m --no-sync $mounts </dev/null
done <<\____SERVER__MOUNTS |
server1 /dev/md10 /dev/md11
server2 /dev/md12 /dev/md13
____SERVER__MOUNTS
# sed -e /^Filesystem/d inlined into Awk below
sort |
# pipe into awk
awk 'BEGIN { print "UDS:\nserver1 & server2"
# Maybe use printf here too
print "Mounted on Free space Disk usage Use% Disk state"
fmt="%-18s %8i %12i %6s %-2s"
}
function status(num) {
# Awk conveniently ignores any trailing string
# so you can compare 95% to 95 numerically
if (num > 95) result="CRITICAL"
else if (num > 90) result="WARNING"
else result="OK"
return(result)
}
! /^Filesystem/ {
printf fmt "\n", $6, $4, $3, $5, status($5)
# EdmCoff''s hack, too lazy to change to legible variable names
# adapted to defer division until we know the final value of n
a+=$2;b+=$3;c+=$4;dd+=$5;n++
}
END { d=dd/n;
printf "\n" fmt "%%\n",
"Grand total:", c, b, int(d), status(d) }'
I obviously have no way to test this with real input, so there are probably minor formatting errors etc. I hope I captured enough of the logic to at least show you how to implement the body of this processing as an Awk script.
Notice the absence of any temporary files (which your original script would fail to clean up if it was interrupted; use trap
) and the use of indentation to help you see the loops and conditionals.