2

I need to make a bash script to compare the space of a vg on redhat servers. What I have so far is:

#!/bin/bash

##VARS
CMD=$(vgs | grep vgSoft | awk -F" " '{print $7}' | awk -F"<" '{print $2}'| awk -F"g" '{print $1}')
SPACE="10.00"

if [[ "$CMD" < "$SPACE" ]]; then
    echo "It's not enough space, you must extend the VG"
    echo "Space is equal to: $CMD GB"
elif [[ "$CMD" == "$SPACE" ]]; then
    echo "It's enough space but consider extend the VG"
elif [[ "$CMD" > "$SPACE" ]]; then
    echo "It's enough space"
    echo "Space is equal to: $CMD GB"
fi

What do I do with this command is obtaing the output of volume groups and parse the data for obtain the desired value vgs | grep vgSoft | awk -F" " '{print $7}' | awk -F"<" '{print $2}'| awk -F"g" '{print $1}' and save it to the CMD variable. Where the output of vgs command is:

[root@server~]# vgs
  VG     #PV #LV #SN Attr   VSize   VFree
  vgSoft   2  13   0 wz--n-  71.99g <26.14g
  vgSys    1  12   0 wz--n- <63.51g <36.52g

So in this case, the result of my CMD variable is 26.14 And I'm making the comparison with the value 10.00 (which is assigned to the SPACE variable).

But I'm having an issue comparing the strings, because is the output of vgs command is for example 9.46 the script says me that "It's enough space" when the output should be "It's not enough space, you must extend the VG". As far I remember I don't be able to use the operators "eq" "gt" "ne" because I'm comparing to strings and not integer values.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Bash only supports integers, you can't compare numbers with decimals. – Barmar Dec 28 '21 at 02:52
  • `<` and `>` are for string comparisons, not numeric. Use `-lt` and `-gt` for numbers. – Barmar Dec 28 '21 at 02:53
  • 2
    You shouldn't use string comparison when comparing numbers. `2 < 10` is false when doing string comparison. – Barmar Dec 28 '21 at 02:54
  • 1
    The string 9.46 is bigger than the string 10.00 because 9 is greater than 1, lexicographically speaking. – Shawn Dec 28 '21 at 02:55
  • Why not? Likewise, I am treating the data as a string and not as a number precisely because a data of type integer cannot have decimals. But I'll try @Barmar – Fede Berbara Dec 28 '21 at 02:56
  • 1
    Use a shell like zsh or ksh that supports floating point math, or a different tool completely to do the comparison. https://mywiki.wooledge.org/BashFAQ/022 has examples – Shawn Dec 28 '21 at 02:57
  • For example, you can do it all in a single awk instance. – Shawn Dec 28 '21 at 03:04
  • 1
    You're already using awk. Go ahead and improve it so it does what you want and also so it's only executed once. – konsolebox Dec 28 '21 at 03:06
  • As an aside, check [Correct Bash and shell script variable capitalization](https://stackoverflow.com/questions/673055/correct-bash-and-shell-script-variable-capitalization) and [useless use of `grep`](http://www.iki.fi/era/unix/award.html#grep) where you also have the dubious honor of a useless `awk | awk` – tripleee Dec 28 '21 at 06:05

3 Answers3

5

With your shown samples, please try following awk code. We can do all this in single awk.

We have an awk variable named space where I have defined value as 10 as per shown attempts of OP, one could change it as per need.

vgs | awk -v space="10" '
FNR==1 || !/vgSoft/{ next }
{
  value=substr($7,2,length($7)-1)+0
}
value<space { 
  print "It\047s not enough space, you must extend the VG"
  next
}
value==space{
  print "It\047s enough space but consider extend the VG"
  next
}
value>space {
  print "It\047s enough space"
}
'

OR in case you have 7th field in lines which could OR couldn't have starting < in its value so to deal with these kind of situations please try following awk code.

vgs | awk -v space="10" '
FNR==1 || !/vgSoft/{ next }
{
  sub(/^</,"",$7)
  value=$7+0
}
value<space { 
  print "It\047s not enough space, you must extend the VG"
  next
}
value==space{
  print "It\047s enough space but consider extend the VG"
  next
}
value>space {
  print "It\047s enough space"
}
'

Explanation: Running vgs command first and sending its standard output as a standard input to awk program. In awk program creating variable space with value of 10 as per shown attempts. Then in main program, checking condition(s) if its line first line OR line does not contain vgSoft string then simply jump to next line. If a line contains vgSoft string then creating a variable named value which will have value from 7th field of current line(without < and g from 7th field), then using 3 conditions to check(if value is equal to OR lesser than OR grater than space or not) accordingly printing statements then.

Fair warning I don't have vgs command with me so I tested this code with putting your sample output of vgs command into an Input_file and running it against awk program and it worked fine for me.

RavinderSingh13
  • 130,504
  • 14
  • 57
  • 93
  • 1
    Thank you for this and for the clearly explanation! It was very helpful and I was able to solve my problem. I didn't know that AWK is so powerful. – Fede Berbara Dec 28 '21 at 03:44
  • Just to ask, if in some cases it had "<" and in others it didn't, how could it be done? – Fede Berbara Dec 28 '21 at 03:45
  • @FedeBerbara, I have added OR solution now, which will handle lines whose 7th fields are either starting from `<` or not it will take care of both cases. Cheers. – RavinderSingh13 Dec 28 '21 at 04:34
0

You may just use the echo command in combination with bc for comparison as shown below

$ SPACE=10.00
$ CMD=9.46
$ echo "${CMD}>${SPACE}" | bc
0
$ CMD=10.46
$ echo "${CMD}>${SPACE}" | bc
1
Rakesh Gupta
  • 3,507
  • 3
  • 18
  • 24
  • It's a good idea, I'm going to test because I don't know if BC is installed on all servers or is a package that comes by default in redhat – Fede Berbara Dec 28 '21 at 03:15
0

Doing it in just awk:

vgs | awk -v space=10.00 '/vgSoft/ {
   free = substr($7, 2, length($7) - 2)+0 # Assumes the < and g will always be there
   if (free < space) {
     print "It'"'"'s not enough space, you must extend the VG"
     print "Space is equal to: " space " GB"
   } else if (free == space) {
     print "It'"'"'s enough space but consider extend the VG"
   } else {
     print "It'"'"'s enough space"
     print "Space is equal to: " space " GB"
   }
   exit
}'
Shawn
  • 47,241
  • 3
  • 26
  • 60
  • The ugly `'"'"'` stuff is for getting single quotes into the output strings without breaking shell quoting. – Shawn Dec 28 '21 at 03:17
  • Thanks for this as I told to RavinderSingh13! It was very helpful and I was able to solve my problem. I didn't know that AWK is so powerful, I should read more about it – Fede Berbara Dec 28 '21 at 03:46
  • What if in some cases I have – Fede Berbara Dec 28 '21 at 03:48
  • @FedeBerbara Then your sample data should include such cases, and the way to extract the number depends on if you want to use GNU awk or generic POSIX awk. – Shawn Dec 28 '21 at 04:25