LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Home Forums Tutorials Articles Register
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 04-29-2012, 10:24 PM   #1
Adol
Member
 
Registered: Feb 2011
Location: Osaka, Japan
Distribution: Gentoo, Opensuse
Posts: 271

Rep: Reputation: 6
trying to create bash for defragmenting xfs drive


Hello,

I'm trying to create a bash script which will check my fragmentation level and defrag if the percentage of fragmentation is over a certain amount.

The commands I want to run are:

Code:
xfs_db -c frag -r /dev/mapper/storage-working
which would give me an output of something like:

Code:
actual 141049, ideal 117368, fragmentation factor 16.79%
after that I want to send the output and somehow create an if command in my bash script.

If the fragmentation is above 15% I want it to automatically run:

Code:
xfs_fsr -v /dev/mapper/storage-working
Which will defrag the drive.

I am really bad with bash scripts. What command should I be looking at to link the information and start my defrag if its higher than 15%?

So far all I have is:
Code:
#! /bin/bash
# script to check and run defrag on xfs file system

echo "first checking fragmentation level of LVM drive"
echo "if drive is more than 16% fragmented proceeding to defrag"
Im still looking online but dont have much direction.

Any ideas?
 
Old 04-30-2012, 12:25 AM   #2
es0teric
Member
 
Registered: Apr 2007
Distribution: Ubuntu
Posts: 105

Rep: Reputation: 19
The first thing you'll want to do is isolate that percentage number. As long as the format of that output is standard, you can use 'awk' to grab a particular column. After you've isolated that value and stored it in a variable, you can write a conditional statement to determine how to proceed.

This page details conditional statements better than I can:
http://www.linuxtutorialblog.com/pos...-if-statements
 
1 members found this post helpful.
Old 04-30-2012, 02:52 AM   #3
Adol
Member
 
Registered: Feb 2011
Location: Osaka, Japan
Distribution: Gentoo, Opensuse
Posts: 271

Original Poster
Rep: Reputation: 6
Quote:
Originally Posted by es0teric View Post
The first thing you'll want to do is isolate that percentage number. As long as the format of that output is standard, you can use 'awk' to grab a particular column. After you've isolated that value and stored it in a variable, you can write a conditional statement to determine how to proceed.

This page details conditional statements better than I can:
http://www.linuxtutorialblog.com/pos...-if-statements
Thank you.

That got me started but Im still having alot of trouble.

My if statement is not being observed.

This is my bash script:

Code:
#! /bin/bash
#  script to check and run defrag on xfs file system

echo "checking fragmentation level of LVM drive"
echo "if drive is more than 20% fragmented proceeding to defrag"

if (( xfs_db -c frag -r /dev/mapper/storage-working | awk '{ print $7 }' ) > 20.00 ); then
        echo "defragmentation is at:"
        xfs_db -c frag -r /dev/mapper/storage-working | awk '{ print $7 }'
        echo "starting to defragment"
else
        echo "defragmentation is at:"
        xfs_db -c frag -r /dev/mapper/storage-working | awk '{ print $7 }'
        echo "no need to defragment"
fi
It follows the first contition no matter what. My output is:

Code:
checking fragmentation level of LVM drive
if drive is more than 20% fragmented proceeding to defrag
defragmentation is at:
19.67%
starting to defragment
it should be telling me there is no need to defragment but its only following the first part of the if statement.

Another way I tried was:

Code:
#! /bin/bash
#  script to check and run defrag on xfs file system

echo "checking fragmentation level of LVM drive"
echo "if drive is more than 20% fragmented proceeding to defrag"

if xfs_db -c frag -r /dev/mapper/storage-working | awk '$7 > 20.00'; then
        echo "defragmentation is at:"
        xfs_db -c frag -r /dev/mapper/storage-working | awk '{ print $7 }'
        echo "starting to defragment"
else
        echo "defragmentation is at:"
        xfs_db -c frag -r /dev/mapper/storage-working | awk '{ print $7 }'
        echo "no need to defragment"
fi
I get:
Code:
checking fragmentation level of LVM drive
if drive is more than 20% fragmented proceeding to defrag
defragmentation is at:
19.67%
starting to defragment
I cant seem to get this bash right.
 
Old 04-30-2012, 04:58 AM   #4
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
With just a quick glance so far:

Code:
if (( xfs_db -c frag -r /dev/mapper/storage-working | awk '{ print $7 }' ) > 20.00 ); then
First of all, the shell can't do floating point operations. It can only compare integer values. You'll have to either strip off the decimals or use awk or bc or similar to do the actual comparison.

Second, the syntax is wrong. Arithmetic operations are done in ((..)) brackets, and command substitution uses $(..).

As a final suggestion, you shouldn't keep running the same external commands over and over. For maximum efficiency, do it once only and store the output in a variable for subsequent use.

I would personally do something like this:

Code:
pct=$( xfs_db -c frag -r /dev/mapper/storage-working | awk '{ print int($7) }' )

if (( pct > 20 )); then
	...

For more info on doing arithmetic in the shell, see here:

arithmetic expressions
 
1 members found this post helpful.
Old 04-30-2012, 08:29 AM   #5
Adol
Member
 
Registered: Feb 2011
Location: Osaka, Japan
Distribution: Gentoo, Opensuse
Posts: 271

Original Poster
Rep: Reputation: 6
Quote:
Originally Posted by David the H. View Post
With just a quick glance so far:

Code:
if (( xfs_db -c frag -r /dev/mapper/storage-working | awk '{ print $7 }' ) > 20.00 ); then
First of all, the shell can't do floating point operations. It can only compare integer values. You'll have to either strip off the decimals or use awk or bc or similar to do the actual comparison.

Second, the syntax is wrong. Arithmetic operations are done in ((..)) brackets, and command substitution uses $(..).

As a final suggestion, you shouldn't keep running the same external commands over and over. For maximum efficiency, do it once only and store the output in a variable for subsequent use.

I would personally do something like this:

Code:
pct=$( xfs_db -c frag -r /dev/mapper/storage-working | awk '{ print int($7) }' )

if (( pct > 20 )); then
	...

For more info on doing arithmetic in the shell, see here:

arithmetic expressions
Thank you. Now I understand how to set a variable and not keep running a command over and over.

My bash script is still not quite working.

I changed it to:
Code:
#! /bin/bash
#  script to check and run defrag on xfs file system

echo "checking fragmentation level of LVM drive"
echo "if drive is more than 15% fragmented proceeding to defrag"

pct=$( xfs_db -c frag -r /dev/mapper/storage-working | awk '{ print int($7) }' )

if (( pct >= 15 )); then
        echo "defragmentation is at:"$pct"%"
        echo "starting to defragment"
else
        echo "defragmentation is at:"$pct"%";
        echo "no need to defragment"
fi
If I set it to
Code:
if (($pct = 19))
because my fragmentation is 19% it seems to work and not give me all the 0's

This is the output I get when trying to use the greater or equal to command:

Code:
checking fragmentation level of LVM drive
if drive is more than 15% fragmented proceeding to defrag
xfs_defrag.sh: line 9: ((: 0
0
0
0
19: syntax error in expression (error token is "0
0
0
19")
defragmentation is at:0 0 0 0 19%
no need to defragment
What is my syntax error. I took a look at the link above and it looks right to me.
 
Old 04-30-2012, 09:13 AM   #6
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Code:
if (($pct = 19))
"=" sets the variable to the value, just as in other contexts. For "is equal to" comparison, use "==".

It's also (generally) unnecessary to use "$" in front of variables in arithmetic contexts. Since only digits and math operators are valid, literal strings are automatically assumed to be variables containing integers.

Please post the full raw output of the xfs_db command, on its own. It looks like you're getting multiple values in the output. At a guess, you're probably reading all of your partitions at once, when you really need to loop through them one at a time. Or there are other, non-data lines that are causing extra output.


BTW, you also have too many quote marks in your echo lines. You only need one set around the whole phrase. As it stands, the variable is unprotected. Not a problem in this script, but it could cause trouble in other situations.

Code:
echo "defragmentation is at:"$pct"%"

	#change to...

echo "defragmentation is at: $pct%"
http://mywiki.wooledge.org/Arguments
http://mywiki.wooledge.org/WordSplitting
http://mywiki.wooledge.org/Quotes

Last edited by David the H.; 04-30-2012 at 09:29 AM. Reason: Edit for more help
 
1 members found this post helpful.
Old 04-30-2012, 01:51 PM   #7
Tinkster
Moderator
 
Registered: Apr 2002
Location: earth
Distribution: slackware by choice, others too :} ... android.
Posts: 23,067
Blog Entries: 11

Rep: Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928Reputation: 928
The numerical comparison will keep failing because awk's $7 will
be a number + a percent sign. David already mentioned stripping
it of decimals (which you didn't do).



Cheers,
Tink
 
Old 04-30-2012, 09:58 PM   #8
Adol
Member
 
Registered: Feb 2011
Location: Osaka, Japan
Distribution: Gentoo, Opensuse
Posts: 271

Original Poster
Rep: Reputation: 6
Thank you very much everyone.

I got it to work now using the same code as above:
Code:
#! /bin/bash
#  script to check and run defrag on xfs file system

echo "checking fragmentation level of LVM drive"
echo "if drive is more than 15% fragmented proceeding to defrag"

pct=$( xfs_db -c frag -r /dev/mapper/storage-working | awk '{ print int($7) }' )

if (( pct >= 5 )); then
        echo "defragmentation is at: $pct%";
        echo "starting to defragment"
else
        echo "defragmentation is at: $pct%";
        echo "no need to defragment"
fi
the problem wasnt the bash script. It was the defrag process.

It seems that after the defrag it wasnt reporting the fragmentation as it should. It was giving errors before the fragmentation %. After I rebooted this went away and now its following my if rule with no problem.

However, if I always need to reboot after a defrag it ruins my plans of creating a cron sript to run the bash script that I made.

I was getting this error:
Code:
invalid numrecs (36345) in bmapbtd block
Do you have any idea how I can get rid of this error without having to reboot my sytem? Like some kind of cleanup after running a defrag process?

Also, Thinkser, could you please explain? Im not sure I understand:
Quote:
The numerical comparison will keep failing because awk's $7 will
be a number + a percent sign. David already mentioned stripping
it of decimals (which you didn't do).
My result comes out as a number without percentages. I thought that was what using integer was for. Could you please explain?
 
Old 05-01-2012, 12:38 AM   #9
David the H.
Bash Guru
 
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852

Rep: Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037Reputation: 2037
Yes, the int function takes care of the percentage sign, as well as the decimals. If we didn't use that, we'd have to remove it some other way. It could just as easily be done with some string munging in bash, for example.


I'm not sure how to help you with the defragger problem, as I don't use xfs. But if you can figure out what command(s) to use to fix it, they could easily be incorporated into the script. Likely you'd just need a simple output check first. If you need help for it you may want give it its own thread.


BTW, when debugging a script, you should usually start by double-checking all your variable values and other inputs and outputs. Insert some echos here and there to view them at various places, and test the commands you're using individually.

Another option is to add "set -x"/"set +x" at various locations in the script. This will toggle debugging mode on and off, and it will print each command with expanded values before it runs them. You can also enable it for the whole script with "#!/bin/bash -x".

There's also a "-v" (verbose) option that you can similarly use.
 
1 members found this post helpful.
Old 05-01-2012, 08:59 AM   #10
Adol
Member
 
Registered: Feb 2011
Location: Osaka, Japan
Distribution: Gentoo, Opensuse
Posts: 271

Original Poster
Rep: Reputation: 6
Thank you very much with all of your help with my bash script.

As for the xfs issue, I want to do some more reaserch before I start a thread about it.

Thank you
 
  


Reply



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
usb drive is type xfs and I can't access Four Linux - Newbie 1 02-07-2009 01:06 AM
Defragmenting Hard Drive nwarp Linux - Newbie 6 12-09-2007 06:19 AM
Mounting an ext3 drive to an xfs Kernel? Corgana Linux - Desktop 4 04-01-2007 09:47 PM
Add drive, format XFS and mount... kailun Slackware 9 09-25-2006 01:45 PM
Hard Drive XFS Partition qwerty_int Linux - Hardware 1 09-20-2004 02:52 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - Newbie

All times are GMT -5. The time now is 05:16 PM.

Main Menu
Advertisement
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
Open Source Consulting | Domain Registration