This question already has answers here:
Floating point comparison with variable in bash [duplicate]
(2 answers)
Closed 6 years ago.
In my custom bash script for server monitoring , which actually made to force my CentOS server take some actions and alert me if resources are overloaded more time than expected, I get the following error
line 17: [: 5.74: integer expression expected *
Now by definition all iostat results are float numbers and I already have used awk in my iostat command (WAIT) so how I can make my bash script to expect one instead of integer ?
** Value 5.74 represents current iostat result
#!/bin/bash
if [[ "`pidof -x $(basename $0) -o %PPID`" ]]; then
# echo "Script is already running with PID `pidof -x $(basename $0) -o %PPID`"
exit
fi
UPTIME=`cat /proc/uptime | awk '{print $1}' | cut -d'.' -f1`
WAIT=`iostat -c | head -4 |tail -1 | awk '{print $4}' |cut -d',' -f1`
LOAD=`cat /proc/loadavg |awk '{print $2}' | cut -d'.' -f1`
if [ "$UPTIME" -gt 600 ]
then
if [ "$WAIT" -gt 50 ]
then
if [ "$LOAD" -gt 4 ]
then
#action to take (reboot, restart service, save state sleep retry)
MAIL_TXT="System Status: iowait:"$WAIT" loadavg5:"$LOAD" uptime:"$UPTIME"!"
echo $MAIL_TXT | mail -s "Server Alert Status" "mymail#foe.foe"
/etc/init.d/httpd stop
# /etc/init.d/mysql stop
sleep 10
# /etc/init.d/mysql start
/etc/init.d/httpd start
fi
fi
fi
CentOS release 6.8 (Final) 2.6.32-642.13.1.el6.x86_64
Normally, you'd need to use something other than native shell math, as described in BashFAQ #22. However, since you're comparing to integers, this is easy: You can just truncate at the decimal point.
[ "${UPTIME%%.*}" -gt 600 ] # truncates your UPTIME at the decimal point
[ "${WAIT%%.*}" -gt 50 ] # likewise
Related
This question already has answers here:
Value too great for base (error token is "09")
(7 answers)
Value too great for base (error token is "08") [duplicate]
(1 answer)
Closed 5 months ago.
I have a script that looks at the current time, does some tasks and notifies me 1 minute before the timer ends. For some reason there is a problem and the script does not pass the condition "IF"
I read that it seems like bash interprets numbers not as a decimal number. I tried to solve the problem by removing the first zero from the string. Bash will understand this as a decimal number and perform a subtraction operation.
For example. Turn off the computer after 10 minutes. Now is 01:00:00. Shutdown at 01:10:00
The script makes a timecode file with name "T01H10M.shutdown" and takes all the necessary numbers of hour and minute from it.
When the time comes to 01:09:00, the script notifies me about the imminent completion of the work.
#Search shutdown time from file name
SearchFilenameDateWhenPCgotoShutdown="$(find /root/ -name '*.shutdown')"
SearchTimeHour=$(echo $SearchFilenameDateWhenPCgotoShutdown | cut -f2 -d "T"| cut -f1 -d "H")
SearchTimeMinute=$(echo $SearchFilenameDateWhenPCgotoShutdown | cut -f2 -d "H" | cut -f1 -d "M")
#Calculation of the penultimate minute and Ńorrection of the subtraction error.
SearchTimeMinuteMinus1=$(($SearchTimeMinute - 1 ))
if [ $SearchTimeMinuteMinus1 -eq -2 ]; then
SearchTimeMinuteMinus1=58;
fi
if [ $SearchTimeMinuteMinus1 -eq -1 ]; then
SearchTimeMinuteMinus1=59
fi
#Determining the current hour and minute
RealTimeHour=$(date "+%H")
RealTimeMinute=$(date "+%M")
if [ $RealTimeMinute = 00 ];
then
RealTimeMinute=0;
else
RealTimeMinute=`echo $RealTimeMinute |sed 's/^0*//'`
fi
#The condition matches the current hour
if [ $SearchTimeHour = $RealTimeHour ]; then
if [ $SearchTimeMinuteMinus1 = $RealTimeMinute ]; then
curl -s "https://api.telegram.org/bla bla bla bla &> /dev/null
fi
And here there is an error that when the current time is in minutes from 00-07 minutes, the condition IF = 00 then = 0 else remove "0" work fine and corrects the number to decimal with a condition. Output 1, 2, 3...7 And when the minute is already 08, the script stops at the stage of checking minutes.
if [ $SearchTimeMinuteMinus1 = $RealTimeMinute ]; then
And I don't understand why!
I tried to do it in a separate script.
B=08
if [ $B = 00 ];
B=0;
else
B=`echo $B |sed 's/^0*//'`
fi
echo $B
He works. Output 8. Why I can't do it in the main script, I don't understand.
Screenshot with each 2 min script run
Help please.
--------------------UPD 4.10.22--------------------
OK! Thank you all for your advice. I fixed the code and it works. But! Another problem :D When the time comes at 59 minutes. An error occurs in stage.
if [ $SearchTimeHour = $RealTimeHour ]; then
Problem
This is very strange! After all, all variables are defined correctly. Any ideas?
Full code:
#!/bin/bash
if ping -c 2 100.100.100.100 | grep "ttl"; then
if ping -c 2 192.168.10.1 | grep "ttl"; then
if ping -c 2 192.168.88.102 | grep "ttl"; then
#OMV name
NameOMV="Standart OMV"
#The option determines how many minutes to turn off the system
ShutDownParameterMinutes=2
#Defining the startmark file in the script
startmark=/root/startmark
#Checking the existence of the startmark file
if [ -f $startmark ]
then
#Recording when to switch off to a variable
SearchFilenameDateWhenPCgotoShutdown="$(find /root/ -name '*.shutdown')"
#Determination of the hour and minute of shutdown
SearchTimeHour=$(echo "$SearchFilenameDateWhenPCgotoShutdown" | cut -f2 -d "T"| cut -f1 -d "H")
SearchTimeMinute=$(echo "$SearchFilenameDateWhenPCgotoShutdown" | cut -f2 -d "H" | cut -f1 -d "M")
#Determination of the hour and minute of shutdown minus 1 minute for notification in telegrams
#Correction of the subtraction error of 2 minutes - 2 minutes becomes 58 minutes, and -1 = 59 minutes
SearchTimeMinuteMinus1=$((SearchTimeMinute - 1 ))
if [ "$SearchTimeMinuteMinus1" -eq -2 ]; then
SearchTimeMinuteMinus1=58
fi
if [ "$SearchTimeMinuteMinus1" -eq -1 ]; then
SearchTimeMinuteMinus1=59
fi
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 SearchTimeMinuteMinus1=${SearchTimeMinuteMinus1}" &> /dev/null
#Determining the current hour and minute
RealTimeHour=$(date "+%H")
RealTimeMinute=$(date "+%M")
RealTimeMinute=$((10#$RealTimeMinute))
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 RealTimeHour=${RealTimeHour}" &> /dev/null
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 RealTimeMinute=${RealTimeMinute}" &> /dev/null
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 TICK $(date "+%d.%m.%Y - %H:%M:%S")" &> /dev/null
#The condition matches the current hour
if [ "$SearchTimeHour" -eq "$RealTimeHour" ]; then
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 Hour OK" &> /dev/null
if [ "$SearchTimeMinuteMinus1" -eq "$RealTimeMinute" ]; then
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 Minute OK" &> /dev/null
rm "$SearchFilenameDateWhenPCgotoShutdown"
rm startmark
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 $NameOMV is less 1 minutes left before shutdown" &> /dev/null
fi
fi
else
#Creating a startmark
touch startmark
#Notification in telegram about the start of the shutdown procedure
echo "OrangePi is creating startmark to offline: $(date "+%d.%m.%Y - %H:%M:%S")" >> shutdownlog.txt
#We determine the time when to turn off
DateWhenPCgotoShutdown=$(date +"T""%H""H""%M""M" --date="$ShutDownParameterMinutes minute")
TimeStampStartName="${DateWhenPCgotoShutdown}.shutdown"
touch "$TimeStampStartName"
chmod +x "$TimeStampStartName"
#Notification in telegram when to turn off the computer
TelegramMessage="OrangePi $NameOMV is creating startmark to offline: $(date "+%d.%m.%Y - %H:%M:%S" --date="$ShutDownParameterMinutes minute")"
echo "${TelegramMessage}" >> shutdownlog.txt
curl -s "https://api.telegram.org/blablabla&text=%F0%9F%93%B7 $TelegramMessage" &> /dev/null
#/sbin/shutdown -h +$ShutDownParameterMinutes
echo "SHUTDOWN"
fi
fi
fi
fi
With respect.
#!/bin/bash
while [ true ]
do
echo "$(top -b -o +%MEM -n 1 | head -n +8 | tail -n 1 | awk '{ print $12";"$10 }');$(date +'%H:%M:%S')" >> RAM.csv
if [ -z "$1" ]; then
sleep 1m
else
sleep "$1"
fi
done
ERROR OUTPUT : date: extra operand '%H:%M:%S'
what is wrong with this?
Below you find a mildly improved version of your script:
#!/usr/bin/env bash
# All output is appended to RAM.csv
exec >> RAM.csv
# Do an infinite loop
while :; do
# Get command with most used memory, print it in CSV format, append time
date "+$(ps -eo ucmd -o '%mem' --sort=-%mem h | awk -v OFS=";" '($1=$1);{exit}');%T"
# sleep $1 seconds, if not defined 1m
sleep "${1:-1m}"
done
I have this script:
#!/bin/bash
# rsync using variables
CPU=$(sar 1 5 | grep "Average" | sed 's/^.* //')
if [ $CPU -lt 100 ]
then
cat mail_content.html | /usr/lib/sendmail -t
else
echo "Normal"
fi
when I am executing it I am getting the following error message:
./monitor_cpu.sh: line 6: [: 99.25: integer expression expected
Normal
I want it to be able to identify that the number x.x (99.25) will be recognized which is not happening right now.
Alternatively, if CPU is not an integer, you can use bc to compare it.
echo "$CPU < 100" | bc
Then if the result is 1, the value of CPU will be less than 100. So you can do:
[ $(echo "$CPU < 100" | bc) -eq 1 ] && echo yes
Or, you can convert it to integer with printf:
printf '%.0f' "$CPU"
The problem is that -eq does not compare floats, as explained here. Thus, you need to use bc.
#!/bin/bash
# rsync using variables
CPU=$(LANG=C sar 1 5 | grep "Average" | sed 's/^.* //')
if (( $(echo "$CPU < 100" |bc -l) ))
then
cat mail_content.html | /usr/lib/sendmail -t
else
echo "Normal"
fi
Code below is supposed to check the memory for user and if its greater than 1000, print message
I keep getting error- line 4: impala: command not found
#!/bin/bash
while [ true ] ;do
used= `ps hax -o rss,user | awk '{a[$2]+=$1;}END{for(i in a)print i"
"int(a[i]/1024+0.5);}' | grep user`
if [[ $used > 1000 ]]; then
echo "user memory is $used"
fi
sleep 5
done
I have tried used= ps hax -o rss,user | awk '{a[$2]+=$1;}END{for(i in a)print i" "int(a[i]/1024+0.5);} | grep user'
and used= 'ps hax -o rss,user | awk '{a[$2]+=$1;}END{for(i in a)print i" "int(a[i]/1024+0.5);}' | grep user'
I need a fresh eye on this. Please help.
In bash, as mentioned [ here ], putting spaces around the equal sign would cause errors, So the right format is
variable_name=value;
Moreover, you may change
while [ true ]
to
while true
Edit
If used has the form impala 600 and you're only interested in the number at the end, then you may do
used="${used##* }"
#Do this just after the your first command.
Finally do
#use -gt for integer comparisons and > for string comparisons
if ! [ -t $used ] && [ $used -gt 1000 ]
then
echo "user memory is $used"
fi
Note: Though the syntax errors in the script is resolved there is no guarantee that the program logic is right
I'm trying to create a simple script that checks if the CPU Usage is at a certain level. I have a Raspberry Pi for this project.
The only issue I have currently is that I have the variable CPU which is the CPU usage, when the script runs, I get the error
line 25: [: 4.8: integer expression expected
I'm not sure why bash returns this if BASH really doesn't care about int, String, etc. like JAVA does. Found that out here.
Also, I have the if statement: if $CPU -gt 1 only for testing (it's supposed to return true right now)
red='\e[0;31m'
yellow='\e[1;33m'
NC='\e[0m' # No Color
echo -e "${NC}Starting Server!${NC}"
echo -e "${red}Errors in red!${NC}"
echo -e "${yellow}Info in yellow!${NC}"
sleep 1
echo -e "\n\n"
##CPU USAGE STUFF
echo -e "${yellow}Current CPU Usage:"
CPU=$(top -bn1 | grep "Cpu(s)" | \
sed "s/.*, *\([0-9.]*\)%* id.*/\1/" | \
awk '{print 100 - $1""}')
echo $CPU %
echo -e "${NC}**********${NC}"
cd /root/mc_server/
sleep 1
##CPU USAGE LOOP CHECKER
while :
do
sleep 5
echo $CPU
if [ $CPU -gt 1 ]
then
echo -e "${red}ALERT! CPU Usage is TOO HIGH!${red}"
fi
done
##
##java -Xmx400M -jar bukkit.jar -o true
The issue is that 4.8 is an non-integer value.
You can use bc to deal with non-integer values like so:
if [[ $(echo "$CPU > 1" | bc -l) -eq 1 ]];
it will return boolean expressions as either 1 for true or 0 for false.