Bash integer expression on IF statement when retrieving free memory - linux

I am getting the below error while running the script memory.sh script:
[root#test tmp]# ./memory.sh
./memory.sh: line 3: [: 2.05028: integer expression expected
Normal
The content of the memory.sh script is:
[root#test tmp]# cat memory.sh
threshold=80
MEMORY=$(free | grep Mem | awk '{print $3/$2 * 100.0}')
if [ ${MEMORY} -gt ${threshold} ]; then
sudo sync;echo 3 > /proc/sys/vm/drop_caches
else
echo "Normal"
fi
Does anyone know how to prevent this error?

The error on the IF statement comes up when retrieving float values from
the Memory.
The following script casts the float memory value to an integer for the comparison:
#!/bin/bash
threshold=80
memory=$(free | grep Mem | awk '{print $3/$2 * 100.0}')
castedMemory=$(echo $memory | cut -d'.' -f1)
if [[ "$castedMemory" -gt $threshold ]]; then
sudo sync
echo 3 > /proc/sys/vm/drop_caches
else
echo "Normal"
fi

Looks like you need to convert the computation result into integer type to be able to compare it. What about that suggestion:
#!/bin/bash
threshold=80
MEMORY=$(free | grep Mem | awk '{print int($3/$2 * 100.0)}')
if [ ${MEMORY} -gt ${threshold} ]
then
sudo sync;echo 3 > /proc/sys/vm/drop_caches
else
echo "Normal"
fi
This does not throw an error for me but outputs a friendly "Normal" ;-)

Related

Script gives me Syntax error: Bad fd number

I have a sh script that throws me the 'bad fd number' error, and I can't really find a solution. So this is my script:
rr_path='RR/'
filename='sample_generation.txt'
logdir='RR/'
bash RR/compute-RR.sh $filename
And this is the error:
sample_generation.txt RR: RR/nonSingletonesRate.sh: 40: Syntax error:
Bad fd number
According to the error, something is wrong in the nonSingletonesRate.sh, which is this one:
#! /bin/bash
# This script computes the rate of non-singletone events (N-grams with
# n=1,2,3,4) of the input textual file. Computation is averaged on
# equally-sized non-overlapped sub-samples, spanning the whole text
#
# Its results can be used to compute the repetition rate of the text
# as geometric mean by means of /hltsrv0/cettolo/bin/geomMean.pl
bindir=`dirname $0`
irstlmdir=/hltsrv1/software/irstlm/irstlm-5.80.01
# Size of subsamples:
sampleSize=1000
fn=$1
out=`basename $fn`
echo $out
for n in 1 2 3 4
do
ls $fn
echo "n=$n"
totN=0
totC=0
offset=0
while [ $offset -gt -1 ]; do
offset=`perl $bindir/selectSubSample.pl $fn __subsample__$$ $sampleSize $offset`
cat __subsample__$$ | perl $bindir/word2ngrams.pl $n > __tmp__$$
$irstlmdir/bin/dict -cs=3 -f=yes -i=__tmp__$$ -sort=yes -c=yes >& __tmp.histo__$$
N=`egrep '^>0' __tmp.histo__$$ | awk '{print $2}'`
totN=`expr $totN + $N`
C=`egrep '^>1' __tmp.histo__$$ | awk '{print $2}'`
totC=`expr $totC + $C`
done
echo $totC $totN | awk '{print $0,100*$1/$2}'
echo ""
done
rm __tmp__$$ __tmp.histo__$$ __subsample__$$
exit
From what I've seen online, it could be a problem of having a >&, and it should be solved by changing it to >. So changing this line should be enough:
$irstlmdir/bin/dict -cs=3 -f=yes -i=__tmp__$$ -sort=yes -c=yes > __tmp.histo__$$
But if a do this, then I get the error:
RR/nonSingletonesRate.sh: 31:
/hltsrv1/software/irstlm/irstlm-5.80.01/bin/dict: not found

BASH: compare the size to a percent part of another file's size

I have the following situation:
A=$(df / | awk 'END{print $4}')
B=$(du -s /tmp | awk '{print $1}')
The condition is to alert when $B is less then 10% of $A size.
the way below i used doesn't seem to recognize '-lt' :
A=$(df / | awk 'END{print $4}')
B=$(du -s /tmp | awk '{print $1}')
if $(($A / $B)) -lt '10'
then echo "Bad case"
fi
: line 8: syntax error near unexpected token `-lt'
: line 8: `if (($A / $B)) -lt '10''
Any ideas how can it be achieved?
A=$(df / | awk 'END{print $4}')
B=$(du -s /tmp | awk '{print $1}')
echo $A $B | awk '{C = 10*B; if (C < A) print "Bad case"}'
You forget [] in if statement:
if [ $(($A / $B)) -lt '10' ]
then echo "BLYAD"
fi
if (( A < 10 * B ))
then
echo "Bad case"
fi
In bash, you can't do fractional arithmetic. Hence you should either rewrite the expression so that it doesn't need fractions or use zsh, which has floating point arithmetic.

LINUX- Checking the internal CPU, RAM usage of JVM's

So I am trying to check the internal CPU and RAM usage from JVM's.
The set up is that we have a single server which hosts 39 JVM's each running its own service and has it's own unique CPU & RAM allocation. So for example it could be set up like the following:
CPU(Cores) RAM(MB)
JVM1 2 300
JVM2 1 50
JVM3 5 1024
These are fictional as I don't have the actual values to hand.
I know the PID's for each of the JVM's but I am wondering how would I see the CPU and RAM usage of each JVM on it's own dissregarding the Host systems usage. Also is it possible to pass multiple PID's into a jstat -gc as I will be looking to script this?.
I know that if I use:
ps -p <PID> -o %CPU %RAM
That will give me the CPU and RAM of that process on the host machine.
Any Help is greatly appreciated.
After playing around for a while I came up with the following script which pulls the memory usage and total memory in use to 2DP:
Script
#!/bin/sh
service=$(mktemp)
jstatop=$(mktemp)
ServiceStatsPre=$(mktemp)
datet=$(date +%Y-%m-%d)
hourt=$(date +%H)
ps -ef | grep java | grep Service | awk '{key=substr($9,31,match($9,"#")-31); serv[key]++}END{for(name in serv){if($9 ~ /Service/){print name}}}'>$service
printf "%-8sService\t\t\t\t%7s PID\t%7s Used\t%7s Total\n" > $ServiceStatsPre
filename=$service
while read -r line; do
if [ ! -z $line ]; then
pid=$(ps -ef | grep java | grep Service |awk -v svc="$line" '{if (match($9,svc)){print $2}}')
rncnt=0
rnag=1
while [ $rnag -eq 1 ]; do
jstat -gc $pid > $jstatop
if [ $? -ne 0 ]; then
sleep 5;
rncnt++;
else
rnag=0
fi
if [ $rncnt -eq 5 ]; then
rnag=0
fi
done
cat $jstatop | awk '{if (NR !=1) print}'|awk -v pid="$pid" -v svc="$line" -v d="$datet" -v h="$hourt" '{printf("%-40s %7d %6.2fMB %6.2fMB %11s %3s\n",svc,pid,($1+$5+$7)/1024,($3+$4+$6+$8)/1024,d,h)}' >> $ServiceStatsPre
fi
done < $filename
#printf "Date,Hour,Service,Used,Total\n" > Service_Stats.csv #Uncomment this line on initial Run to create file with headders
cat $ServiceStatsPre | awk '{if (NR !=1) print}' |
awk '{
printf("%-1s,%1s,%1s,%4.2f,%4.2f\n",$5,$6,$1,$3,$4);
}' >> Service_Stats.csv
rm $service;
rm $jstatop;
rm $ServiceStatsPre;
Breakdown
ps -ef | grep java | grep Service | awk '{key=substr($9,31,match($9,"#")-31); serv[key]++}END{for(name in serv){if($9 ~ /Service/){print name}}}'>$service
This is returning the name of the Service and putting it to a tempary file $service
printf "%-8sService\t\t\t\t%7s PID\t%7s Used\t%7s Total\n" > $ServiceStatsPre
This is just creating Headings in a Temp file $ServiceStatsPre (I know this isn't needed but I was originally using it to debug to a file not a temp file)
Outer While loop
filename=$service
if [ ! -z $line ]; then
while read -r line; do
pid=$(ps -ef | grep java | grep Service |awk -v svc="$line" '{if (match($9,svc)){print $2}}')
rncnt=0
rnag=1
...
cat $jstatop | awk '{if (NR !=1) print}'|awk -v pid="$pid" -v svc="$line" -v d="$datet" -v h="$hourt" '{printf("%-40s %7d %6.2fMB %6.2fMB %11s %3s\n",svc,pid,($1+$5+$7)/1024,($3+$4+$6+$8)/1024,d,h)}' >> $ServiceStatsPre
fi
done < $filename
This is first checking to see if the line that it is passing in is not empty (if [ ! -z $line ]; then) then it is extracting the PID for each of the services in the temp file $service and is setting a check (rnag) + retry counter (rncnt). The final part of this outer while loop is calculating the stats, memory usage in MB (($1+$5+$7)/1024), Total Memory used (($3+$4+$6+$8)/1024) as well as retuning the PID,Service Name,Date and Hour.
Inner While Loop
...
while [ $rnag -eq 1 ]; do
jstat -gc $pid > $jstatop
if [ $? -ne 0 ]; then
sleep 5;
rncnt++;
else
rnag=0
fi
if [ $rncnt -eq 5 ]; then
rnag=0
fi
done
...
This is to basically ensure that the jstat is running correctly and isn't returning an error.
The final part of this script:
#printf "Date,Hour,Service,Used,Total\n" > Service_Stats.csv #Uncomment this line on initial Run to create file with headders
cat $ServiceStatsPre | awk '{if (NR !=1) print}' |
awk '{
printf("%-1s,%1s,%1s,%4.2f,%4.2f\n",$5,$6,$1,$3,$4);
}' >> Service_Stats.csv
is just to resolve the formatting and put it into a format so that it can be used in a CSV.
Output
This script out puts like the following:
Date,Hour,Service,Used,Total
2016-07-03,07,undMFSAdapterServiceVM,331.00,188.87
2016-07-03,07,entSCSServiceVM,332.50,278.19
2016-07-03,07,kServiceVM,457.50,132.91
2016-07-03,07,ServiceTuTrackVm,432.00,282.66
2016-07-03,07,ter1WMSAdapterServiceVm,233.00,77.02
2016-07-03,07,kingMFSAdapterServiceVM,451.50,126.69
2016-07-03,07,erBuilderServiceVM,261.50,211.27
2016-07-03,07,ter3MFSAdapterServiceVM,449.50,210.23
2016-07-03,07,rServiceVM1,1187.00,529.26
2016-07-03,07,rServiceVM2,597.50,398.43
2016-07-03,07,rServiceVM3,2786.00,819.30
2016-07-03,07,rServiceVM4,451.50,163.13
2016-07-03,07,MessagingServiceVm,457.50,357.11
2016-07-03,07,viceVM,444.50,263.59
2016-07-03,07,ServiceVM,1910.50,909.19
2016-07-03,07,undPackingMFSAdapterServiceVM,208.00,113.51
2016-07-03,07,gisticLockServiceVM,245.00,173.05
2016-07-03,07,kingMFSAdapterServiceVM,781.50,327.13
2016-07-03,07,ferWMSAdapterServiceVm,196.00,84.02
2016-07-03,07,geMFSAdapterServiceVM,499.50,256.91
2016-07-03,07,ferMFSAdapterServiceVM,456.50,246.89
2016-07-03,07,kingWMSAdapterServiceVm,195.00,73.70
2016-07-03,07,AdapterServiceVm,149.50,72.62
2016-07-03,07,ter2MFSAdapterServiceVM,455.00,136.02
2016-07-03,07,ionServiceVM,484.00,240.46
2016-07-03,07,ter3WMSAdapterServiceVm,266.00,138.70
2016-07-03,07,iceVm,135.50,106.07
2016-07-03,07,viceVm,3317.00,1882.15
2016-07-03,07,entBCSServiceVM,356.50,143.93
2016-07-03,07,ServiceVm,951.00,227.12
2016-07-03,07,lingServiceVM,145.50,76.61
2016-07-03,07,entDBHServiceVM,182.50,4.63
2016-07-03,07,kingWMSAdapterServiceVm,208.00,103.13
2016-07-03,07,gingServiceVM,1529.50,235.84
2016-07-03,07,ServiceVM,249.50,131.78
2016-07-03,07,ter1MFSAdapterServiceVM,453.00,394.11
2016-07-03,07,AdapterServiceVM,461.00,208.41
2016-07-03,07,ter2WMSAdapterServiceVm,178.50,79.93
2016-07-03,07,AdapterServiceVm,395.00,131.08
2016-07-03,07,ingServiceVM,184.50,126.28
The $3 has been trimmed just to hide service names etc..
Helpful Links
A nice explanation of jstat -gc output

bash error: 2: integer expression expected

I have a problem with a simple bash script..
#!/bin/bash
libc_main_ver=$(dpkg -l |grep libc6 |awk '{print$3}' |awk -F .
'{print$1}'|xargs -n 1)
if [ "$libc_main_ver" -eq 2 ] ;then
echo ok
else
echo nope
fi
exit 0
When i try execute the script it gives me the error:
2: integer expression expected
What's the problem?
dpkg -l |grep libc6 |awk '{print$3}' |awk -F . '{print$1}'|xargs -n 1
This prints only 2 not other values.
Some suggestions?
Insert
echo "<$libc_main_ver>"
after the first line and the error will be obvious. Very likely there's a space or newline in there somewhere which you shouldn't numerically compare with 2.
Very esoteric: the problem could be the literal in -eq 2 as well. If it is followed by a carriage return character, I can somewhat reproduce your error message:
$ test "2" -eq 2^R
bash: test: 2: integer expression expected
where ^R is a literal carriage return entered with CTRL-V CTRL-R. To verify or exclude this, run od -bc nameofyourscript
What if you tried this:
#!/bin/bash
libc_main_vers=$(dpkg -l | grep libc6 | awk '{ print $3 }' | awk -F . '{ print $1 }')
for ver in ${libc_main_vers}; do
if (( ver == 2 )); then
echo ok
else
echo nope
fi
done
exit 0
Here is another version:
#!/bin/bash
libc_full=$(dpkg -l | grep libc6 | head -n 1 | awk '{ print $3 }')
libc_main=$(echo ${libc_full} | grep -o "^[0-9]*")
libc_update=$(echo ${libc_full} | grep -o "[0-9]*$")
if (( libc_main == 2 )); then
echo "Main version is OK"
if (( libc_update >= 7 )); then
echo "Update version is OK"
exit 0
fi
fi
exit 1
It's unclear whether you require all the packages you list to have a major version number 2, or are just verifying that at least one of them does.
Anyway, if we start with the observation that grep foo | awk { print $1 } can usually be refactored into a single Awk script awk '/foo/ { print $1 }' we can already simplify your script; but it sometimes makes sense to refactor basically all of it into Awk. Perhaps like this:
dpkg -l 'libc6*' | awk '$3 !~ /^2\./ { exit 1 }' && echo ok || echo nope
If you are satisfied with just one package meeting the condition, change to something like
dpkg -l 'libc6*' | awk '$3 ~ /^2\./ { exit 0 } END { exit 1 }' && echo ok || echo nope
As always, foo && success || failure is a shorthand for
if foo; then
success
else
failure
fi
where the longhand probably makes sense if your real script needs to do something moderately more complex than just echo a value.
Do note that the output from dpkg -l is not necessarily suitable for scripts. Maybe use dpkg-query -f '${Version}\n' -W 'libc6' instead for robustness.

integer expression expected error.

I don't know why I am getting this error --> : integer expression expected: [: 82
value 82 comes from CURRENT. I am trying to grab the disk space usage and assign to variable called CURRENT and then email out. I don't know where I am going wrong? Any help is appreciated.
#!/bin/bash
ADMIN=email#email.com
THRESOLD=80
CURRENT=$(df -H | grep '/dev/mapper/cvs-cvs' | awk '{ print $5}' | cut -d'%' -f1)
if [ $CURRENT -ge $THRESOLD ]; then
echo "My CVS disk space usage is $CURRENT %" | mailx -s "Disk Space Usage" $ADMIN
fi
Probably your script is in DOS format that the assignment includes \r The extra value appended to the number causes the error. Try converting it first with either of the following commands:
sed -i 's|\r||' script
dos2unix script
It looks like your CURRENT value is not being assigned to an integer from the command substitution output.
I'd recommend running df on the directory you want, then parse the output.
#!/bin/bash
ADMIN=email#email.com
THRESOLD=80
read -ra DF_OUT < <(df -H /dev/mapper/cvs-cvs 2>&1|tail -n 1)
if [[ ${DF_OUT[#]} != "df:"* ]]; then
CURRENT=${DF_OUT[4]/\%/}
if [ $CURRENT -ge $THRESOLD ]; then
echo "My CVS disk space usage is $CURRENT %" | mailx -s "Disk Space Usage" $ADMIN
fi
else
echo -e "df encountered the following error:\n$DF_OUT"
fi
This first checks for an error on the df output before proceeding to parse the results for disk usage.
As others suggested, using -x with the script helps diagnose things.
try
#!/bin/bash
ADMIN=email#email.com
let "THRESOLD=80"
declare -i CURRENT
let CURRENT=$(df -H | grep '/dev/sda1' | awk '{ print $5}' | cut -d'%' -f1)
if (($CURRENT >= $THRESOLD )) ; then
echo "My CVS disk space usage is $CURRENT %" | mailx -s "Disk Space Usage" $ADMIN
fi

Resources