LinuxQuestions.org
Visit the LQ Articles and Editorials section
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie
User Name
Password
Linux - Newbie This Linux forum is for members that are new to Linux.
Just starting out and have a question? If it is not in the man pages or the how-to's this is the place!

Notices

Reply
 
Search this Thread
Old 07-28-2012, 04:57 PM   #1
bluethundr
Member
 
Registered: Jun 2003
Location: Summit, NJ
Distribution: CentOS 5.4
Posts: 122

Rep: Reputation: 15
Thumbs down bash script does not enter loop


Hello

I am attempting a bash script that checks disk space on a host. What I'd like to be able to do is to iterate through a list of disks and report on the space free of the disks in the list.

Here is what I was able to come up with:

Code:
#!/bin/bash
volume1='/disk0'
volume2='/global/disk01_01'
volume3='/global/disk02_01'
volume4='/global/backup'
critspace=20
warnspace=40
critpercent=95
warnpercent=90

for i in $volume{1..4}
do

echo $i



    spacefree=$(df -h $i | awk '{print $4}' | grep -v avail | sed 's/G//')
    echo "spacefree $spacefree"
    percentcapacity=$(df -h $i | awk '{print $5}' | grep -v capacity | sed 's/%//')
    echo "percentfree $percentcapacity"

    if [ $spacefree -le $critspace ] && [ $percentcapacity -ge $critpercent  ]; then
       echo "NOK $spacefree free and $percentcapacity user on $i"
       exit 2

    elif [ $spacefree -le $warnspace  ] && [ $percentcapacity -ge $warnpercent  ]; then
       echo "WARNING $spacefree free and $percentcapacity user on $i"
       exit 1

    else
       echo "ALL OK"
       exit 0


fi


done
And this is the output from the script:
Code:
[db-host:root:~]#./check_ora_filesys.sh 
/disk0
spacefree 23
percentfree 47
ALL OK
For some reason the code is not looping through the list of volumes as I'd hoped.

I notice that if I move the placement of the 'done' statement to terminate the loop before the code I'm hoping to execute, the looping succeeds.


Code:
#!/bin/bash
volume1='/disk0'
volume2='/global/disk01_01'
volume3='/global/disk02_01'
volume4='/global/backup'
critspace=20
warnspace=40
critpercent=95
warnpercent=90

for i in $volume{1..4}
do

echo $i


done

    spacefree=$(df -h $i | awk '{print $4}' | grep -v avail | sed 's/G//')
    echo "spacefree $spacefree"
    percentcapacity=$(df -h $i | awk '{print $5}' | grep -v capacity | sed 's/%//')
    echo "percentfree $percentcapacity"

    if [ $spacefree -le $critspace ] && [ $percentcapacity -ge $critpercent  ]; then
       echo "NOK $spacefree free and $percentcapacity user on $i"
       exit 2

    elif [ $spacefree -le $warnspace  ] && [ $percentcapacity -ge $warnpercent  ]; then
       echo "WARNING $spacefree free and $percentcapacity user on $i"
       exit 1

    else
       echo "ALL OK"
       exit 0


fi

This is the output if I perform this test

Code:
[db-host:root:~]#./check_ora_filesys.sh 
/disk0
/global/disk01_01
/global/disk02_01
/global/backup
spacefree 117
percentfree 21
ALL OK
Thanks, and I'd appreciate any input you may have on this.
 
Old 07-28-2012, 07:40 PM   #2
pixellany
LQ Veteran
 
Registered: Nov 2005
Location: Annapolis, MD
Distribution: Arch/XFCE
Posts: 17,802

Rep: Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728Reputation: 728
Quick guess: Those "exit" commands are taking you out of the for loop. Check the syntax and usage for "exit".
 
Old 07-28-2012, 08:42 PM   #3
etech3
Senior Member
 
Registered: Jul 2009
Location: Virginia
Distribution: Debian Stable Testing Sid Slackware CentOS
Posts: 1,055
Blog Entries: 2

Rep: Reputation: 44
You may want to try only one disk at a time for now.

Try replacing your exit with
Code:
echo $?
at each stage. If everything is good you should get a 0 on the screen.

If not, it will tell you at what step the error is.

Good Luck !
 
Old 07-29-2012, 06:31 AM   #4
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Debian sid + kde 3.5 & 4.4
Posts: 6,823

Rep: Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949Reputation: 1949
Yes, the exit commands will break the script at that point, as long as the conditions match.

Probably the best you can do is save a "status" variable and exit with that at the end. It will only show the status of the last loop iteration though, unless you write something that stores and prints the outputs of all the drives individually.


I would also change the script to use a single array instead of a brace expansion. Much cleaner. It would also be more efficient to store the output of df once, and parse that for the values you want. You can then use parameter substitutions to extract them more efficiently than with awk/sed/grep. The fewer calls to external tools the better, usually.

Finally, when using bash or ksh, it's recommended to use [[..]] for string/file tests, and ((..)) for numerical tests. Avoid using the old [..] test unless you specifically need POSIX-style portability.

http://mywiki.wooledge.org/ArithmeticExpression
http://mywiki.wooledge.org/BashFAQ/031
http://wiki.bash-hackers.org/commands/classictest
http://wiki.bash-hackers.org/syntax/...nal_expression


Here's the modified version I came up with:

Code:
#!/bin/bash

volumes=( '/disk0' '/global/disk01_01' '/global/disk02_01' '/global/backup' )

critspace=20
warnspace=40
critpercent=95
warnpercent=90

for i in ${volumes[@]}"; do

	echo "Processing drive $i"

	#store the output of df in an array
	dfoutput=( $( df -h "$i" | cut -d $'\n' -f2 ) )

	#extract and format the desired fields and echo the results
	spacefree=${dfoutput[3]%G}
	percentcapacity=${dfoutput[4]%\%}

	echo "spacefree $spacefree"
	echo "percentfree $percentcapacity"

	#compare current stats to critical values

	if (( spacefree <= critspace && percentcapacity >= critpercent )); then

		echo "NOK $spacefree free and $percentcapacity user on $i"
		status=2       

	elif (( spacefree <= warnspace && percentcapacity >= warnpercent )); then

		echo "WARNING $spacefree free and $percentcapacity user on $i"
		status=2

	else

		echo "ALL OK"

	fi

done

exit "${status:-0}"
Note that this simply sets the script's exit status to "2" if any of the devices turn up with warnings, which is what I imagine you'd want to happen. Again, more detailed error messages would require extra work.

Notice also how I stored the output of df into an array too (after using cut to chop off the first line), making it easier to access the individual fields.

Actually we could probably even skip using cut and just change it to extract fields 10 and 11 instead.

Last edited by David the H.; 07-29-2012 at 06:39 AM. Reason: minor code change
 
  


Reply

Tags
bash


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Script to Hit 'Enter' key multiple times in bash script. nithinmp Ubuntu 7 07-19-2012 07:01 AM
how to loop over text file lines within bash script for loop? johnpaulodonnell Linux - Newbie 8 04-05-2011 09:18 AM
bash script, empty (enter button pushing only) value catching junust Programming 2 12-25-2008 04:18 AM
BASH: cannot enter special-named dir from script Roger Krowiak Programming 3 08-24-2006 06:19 AM
Testing for enter in bash script bwysocki Programming 8 06-16-2005 09:11 AM


All times are GMT -5. The time now is 11:14 PM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration