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 |
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Are you new to LinuxQuestions.org? Visit the following links:
Site Howto |
Site FAQ |
Sitemap |
Register Now
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
|
|
04-29-2012, 10:24 PM
|
#1
|
Member
Registered: Feb 2011
Location: Osaka, Japan
Distribution: Gentoo, Opensuse
Posts: 273
Rep:
|
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?
|
|
|
04-30-2012, 12:25 AM
|
#2
|
Member
Registered: Apr 2007
Distribution: Ubuntu
Posts: 105
Rep:
|
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.
|
04-30-2012, 02:52 AM
|
#3
|
Member
Registered: Feb 2011
Location: Osaka, Japan
Distribution: Gentoo, Opensuse
Posts: 273
Original Poster
Rep:
|
Quote:
Originally Posted by es0teric
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.
|
|
|
04-30-2012, 04:58 AM
|
#4
|
Bash Guru
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852
|
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.
|
04-30-2012, 08:29 AM
|
#5
|
Member
Registered: Feb 2011
Location: Osaka, Japan
Distribution: Gentoo, Opensuse
Posts: 273
Original Poster
Rep:
|
Quote:
Originally Posted by David the H.
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 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.
|
|
|
04-30-2012, 09:13 AM
|
#6
|
Bash Guru
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852
|
" =" 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.
|
04-30-2012, 01:51 PM
|
#7
|
Moderator
Registered: Apr 2002
Location: earth
Distribution: slackware by choice, others too :} ... android.
Posts: 23,067
|
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
|
|
|
04-30-2012, 09:58 PM
|
#8
|
Member
Registered: Feb 2011
Location: Osaka, Japan
Distribution: Gentoo, Opensuse
Posts: 273
Original Poster
Rep:
|
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?
|
|
|
05-01-2012, 12:38 AM
|
#9
|
Bash Guru
Registered: Jun 2004
Location: Osaka, Japan
Distribution: Arch + Xfce
Posts: 6,852
|
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.
|
05-01-2012, 08:59 AM
|
#10
|
Member
Registered: Feb 2011
Location: Osaka, Japan
Distribution: Gentoo, Opensuse
Posts: 273
Original Poster
Rep:
|
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
|
|
|
All times are GMT -5. The time now is 10:57 AM.
|
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.
|
Latest Threads
LQ News
|
|