result of "less than" operator in bash script - bash

I'm trying to do a script which downloads a file and if it takes less than 'x' seconds it's a pass but from some reason I can't get it to work properly, i've tried '<=' '-lt' in the below example it's always 'FAST' i'e 2.09 FAST
#!/bin/bash
file=&(time -p wget -O /dev/null -q http://site/file.iso ) 2>&1 | grep real | sed -e s/real//g -e s/' '//g
if [ $file <= 1 ]
then
echo "FAST"
else
echo "SLOW"
fi

The bash builtin time outputs directly to your terminal, not to a stdio channel.
You'll need to use /bin/time which uses stderr:
$ time -p sleep 1 >/dev/null 2>&1
real 1.00
user 0.00
sys 0.00
$ /bin/time -p sleep 1
real 1.00
user 0.00
sys 0.00
$ /bin/time -p sleep 1 2>/dev/null
$
So:
$ command time -p sleep 1 2>&1 | awk -v limit=0.5 '$1 == "real" {exit ($2 <= limit)}'
$ echo $?
0
$ command time -p sleep 1 2>&1 | awk -v limit=1.5 '$1 == "real" {exit ($2 <= limit)}'
$ echo $?
1
and then
limit=1 # 1 second
if command time -p wget -O /dev/null -q http://site/file.iso |
awk -v lmt=$limit '$1 == "real" {exit ($2 <= lmt)}'
then
echo "FAST"
else
echo "SLOW"
fi

To capture the output of time you need curly braces:
file=$( { time -p wget -O /dev/null -q http://site/file.iso ; } 2>&1 | grep real | sed -e s/real//g -e s/' '//g )
Bash can't do floating-point calculations, so you can use bc for that:
[[ $( echo $file' <= 1.0' | bc ) == 1 ]] && echo FAST || echo SLOW

Related

CPU monitoring script not triggering properly

I was wondering if anyone could help with the reasons that this is not triggering properly
HOSTNAME=`hostname -s`
LOAD=25.00
CAT=/bin/cat
MAILFILE=/home/jboss/monitor.mail
MAILER=/bin/mail
mailto="bob#bob.bob"
CPU_LOAD=`sar -P ALL 1 10 |grep 'Average.*all' |awk -F" " '{print 100.0 -$NF}'`
if [[ $CPU_LOAD > $LOAD ]];
then
PROC=`ps -eo pcpu,pid -o comm= | sort -k1 -n -r | head -1`
echo -e "Please check processes on ${HOSTNAME} the value of cpu load is $CPU_LOAD%.
Highest process is: $PROC" > $MAILFILE
$CAT $MAILFILE | $MAILER -s "CPU Load is on ${HOSTNAME} is $CPU_LOAD %" $mailto
fi
This seems to be working properly for the sar and ps however I'm still getting alerts emailed for things like CPU Load is 3.18%. Unless I'm missing something it shouldn't trigger unless load is greater than 25%.
It seems though that it's more doing if load is greater than 2.5% Any suggestions?
Thank you
Instead of using:
if [[ $CPU_LOAD > $LOAD ]];then
you must use
if [[ $CPU_LOAD -gt $LOAD ]]; then
Bash only handles integers, so to use higher precision, you could do something like this:
cpu_limit=25
# read the 5min load-average straight from the special file on /proc
read -r _ load_avg _ </proc/loadavg
# multiply by 100 for precision
load_avg=$(bc <<<"scale=0; $load_avg * 100 / 1")
# compare numbers with (( )) instead
if (( load_avg > cpu_limit )); then
...
fi
Try this code - (Tested - working fine)
$ cat f.sh
HOSTNAME=$(hostname -s)
LOAD=25.00
MAILFILE=$HOME/a.txt
MAILER=/bin/mailx
mailto="vipinkumarr89#gmail.com"
CPU_LOAD=$(sar -P ALL 1 10 |grep 'Average.*all' |awk -F" " '{print 100.0 -$NF}')
if [[ $CPU_LOAD > $LOAD ]];then
{
PROC=$(ps -eo pcpu,pid -o comm= | sort -k1 -n -r | head -1)
echo -e "Please check processes on ${HOSTNAME} the value of cpu load is $CPU_LOAD%.
Highest process is: $PROC" > $MAILFILE
cat $MAILFILE | $MAILER -s "CPU Load is on ${HOSTNAME} is $CPU_LOAD %" $mailto
}
fi

Bash Script issue, command not found, PATH seems to be correct

I have a issue with my Script, i am just trying to fingure out if my screen session is running or not (line 19).
The rest of the script is working.
#!/bin/bash
echo $PATH // /usr/local/bin:/usr/bin:/bin:/usr/local/games:/usr/games
echo "0"
content=$(wget http://interwebs.com/index.php?page=count -q -O -)
z=$(($content / 5))
z=$(($z + 1))
echo $z // 4
lockfile=/var/tmp/mylock
if ( set -o noclobber; echo "$$" > "$lockfile") 2> /dev/null; then
trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT
# do stuff here
x=1
count=0
while [ $x -le $z ]
do
$req ="$(ps -ef | grep -i mystatus$count | grep -v grep)"
if [ "$req" = "" ]; then
# run bash script
screen -amds mystatus$count /usr/bin/wget --spider interwebs.com/index.php?page=cronwhatsoever$(( $count +1))-$(( $count +5))
else
echo "Cron running"
fi
x=$(( $x + 1 ))
count=$(( $count +5))
done
# clean up after yourself, and release your trap
rm -f "$lockfile"
trap - INT TERM EXIT
else
echo "Lock Exists: $lockfile owned by $(cat $lockfile)"
fi
sleep 15
It returns line 19: =: command not found. Actually running:
ps -ef | grep -i bukkit | grep -v grep
Works without issues if i run it directly in my Terminal, so any idea how to solve this issue?
I guess it something PATH related but grep is located in /bin/grep.
$req ="$(ps -ef | grep -i mystatus$count | grep -v grep)"
should be
req="$(ps -ef | grep -i mystatus$count | grep -v grep)"
Don't use $ on the left-hand side of an assignment, and you must not have spaces around the =

How to run one command if a previous command succeeds, otherwise run another command

I am trying to check if a process (assume it is called some_process) is running on a server. If it is, then echo 1, otherwise echo 0.
This is the command that I am using but it only works partially (more info below). Note that I need to write the script in one line.
ps aux | grep some_proces[s] > /tmp/test.txt && if [ $? -eq 0 ]; then echo 1; else echo 0; fi
Note: The [s] in some_proces[s] is to prevent grep from returning itself.
If some_process is running, then "1" gets echoed, which is fine. However, if some_process is not running, nothing gets echoed.
There is no need to explicitly check $?. Just do:
ps aux | grep some_proces[s] > /tmp/test.txt && echo 1 || echo 0
Note that this relies on echo not failing, which is certainly not guaranteed. A more reliable way to write this is:
if ps aux | grep some_proces[s] > /tmp/test.txt; then echo 1; else echo 0; fi
&& means "and if successful"; by placing your if statement on the right-hand side of it, you ensure that it will only run if grep returns 0. To fix it, use ; instead:
ps aux | grep some_proces[s] > /tmp/test.txt ; if [ $? -eq 0 ]; then echo 1; else echo 0; fi
(or just use a line-break).
Use grep -vc to ignore grep in the ps output and count the lines simultaneously.
if [[ $(ps aux | grep process | grep -vc grep) > 0 ]] ; then echo 1; else echo 0 ; fi
You can make full use of the && and || operators like this:
ps aux | grep some_proces[s] > /tmp/test.txt && echo 1 || echo 0
For excluding grep itself, you could also do something like:
ps aux | grep some_proces | grep -vw grep > /tmp/test.txt && echo 1 || echo 0
pgrep -q some_process && echo 1 || echo 0
more oneliners here

[: : bad number on the bash script

This is my bash script:
#!/usr/local/bin/bash -x
touch /usr/local/p
touch /usr/local/rec
DATA_FULL=`date +%Y.%m.%d.%H`
CHECK=`netstat -an | grep ESTAB | egrep '(13001|13002|13003|13004|13061|13099|16001|16002|16003|16004|16061|16099|18001|18002|18003|18004|18061|18099|20001|20002|20003|20004|20061|20099|13000|16000|18000|20000)' | awk '{ print $5 }' | sort -u | wc -l`
netstat -an | grep ESTAB | egrep '(13001|13002|13003|13004|13061|13099|16001|16002|16003|16004|16061|16099|18001|18002|18003|18004|18061|18099|20001|20002|20003|20004|20061|20099|13000|16000|18000|20000)' | awk '{ print $5 }' | sort -u | wc -l > /usr/local/www/p
STAT=`cat /usr/local/www/rec`
if [ "$CHECK" -gt "$STAT" ]; then
echo $CHECK"\n"$DATA_FULL > /usr/local/p
fi
Ofcourse I've runned chmod +x script.sh and then sh script.sh, then I receive the following message: [: : bad number.
Why does it happends?
Run your script using
sh -x script.sh
It'll print every line it executes and the variable output.
Run the netstat command and stat command outside and check.
If these are integer for sure, use this syntax,
if [ "0$(echo $CHECK|tr -d ' ')" -gt "0$(echo $STAT|tr -d ' ')" ];
A simple hack. Only works if $STAT is always either empty or positive number.
Are you sure that both STAT and CHECK are numbers that can be compared with -gt?
probably your /usr/local/www/rec is empty. Try
STAT=`cat /usr/local/www/rec 2>/dev/null || echo 0`
maybe.

Error Handling on bash script

Infinite loop on bash script and I want to run forever but (I guess) something goes wrong script is killed. Is there any way like try-catch, just continue to running forever, unconditionaly.
#!/bin/bash
iteration=0
for (( ; ; ))
do
process_id=`ps -ef | grep java | grep TEST | awk '{print $2}' `
kill_command='kill -3 '$process_id
time=`date | awk '{print substr($4,0,5)}' `
last_write=`ls -l /files/*.txt | awk '{print $8}' `
if [ "$time" != "$last_write" ]
then
$kill_command
sleep 1
$kill_command
sleep 1
$kill_command
sleep 1
/test/show_queue.sh
fi
let "iteration+=1"
if [ "$iteration" == "30" ]
then
let "iteration=0"
$kill_command
echo '------------' >> memory_status.log
date >> memory_status.log
prstat -n 7 1 1 >> memory_status.log
echo '------------' >> memory_status.log
/test/show_queue.sh
fi
sleep 60
done
A very simple way to do it is to use two scripts. One with the loop and one which does the killing task :
for (( ; ; ))
do
DoKillingTask
rc=$? # <- You get the return code of the script and decide what to do
done
If it continues to be killed, Mikel (in comment of your question) is right.

Resources