i hope that you can help me to give me ideas about my code, because i do not know how can i do for validate if the script enter two times followed in 20 minutes in the if condition.
rc=0
while [ $rc -ne 1 ]; do
do
ping 192.168.1.89
if [ "$?" -ne "0" ]; then
sleep 600 # this are 10 minutes
# here i need to validate if this script enters two times followed in 20 minutes
continue
else
continue
fi
done
any help will be welcome, thanks
It looks like you are monitoring an IP for loss of connectivity, and you want to take action if two pings 10 minutes apart fail. To achieve this you can just use a counter.
failures=0
rc=0
while [ $rc -ne 1 ]; do
do
ping 192.168.1.89
if [ $? -ne 0 ]; then
((failures++))
echo Ping failures: $failures
if (( failures < 2 )); then
sleep 600
else
echo Max failures hit
fi
else
failures=0
fi
done
You might need to modify the ping commandline to send a maximum number of pings (e.g. use -c 3 to send a maximum of 3). And you might want to redirect ping output to /dev/null.
Related
I'm trying to write a script which helps me to search in log for a phrase "started".
The script that I have until now looks like this:
#!/bin/bash
greperg=
i=3
echo "Web server is going to be polled"
while
i=`expr $i - 1`
#polling
echo "Polling Nr. $i"
grep -q '^started$' log
greperg=$?
#test, if it goes on
test "$greperg" -gt 0 -a "$i" -gt 0
do
#waiting
echo 'waiting ...'
sleep 1
done
if test "$greperg" -eq 0
then
echo "Web server has started"
else
echo -n "Web server is not started"
fi
valid=''
while ((!valid)); do
echo - "Do you want to poll again? (J/N)"
read -t 5 answer
case "$answer" in
[Jj]) result=1; valid=1;;
[Nn]) result=0; valid=1;;
"") result=0; valid=1;;
*) valid=0 ;;
esac
done
echo
if ((result));then
: # ...............(repeat the process again, if its not found ask max 5 times)
else
echo "Timeout"
fi
exit 0
From line 38, I don't know how to re-run it, can anybody help?
What i'm looking for:
The polling should be expanded: If after the 3 attempts that word (started) is still not there, then ask the user with a (Y / N) query whether more should be polled 3 times or not.
The user should be asked a maximum of 5 times
(So a maximum of 3 × 6 = 18 times is polled).
At the very end please state what the status reached is (see example below).
polling ...
Web server has not started yet.
Wait ...
polling ...
Web server has not started yet.
Wait ...
polling ...
Web server has not started yet.
Should it be polled again (Y / N)? _ Y
polling ...
Web server has not started yet.
Wait ...
polling ...
Web server has not started yet.
Wait ...
polling ...
Web server has not started yet.
Should it be polled again (Y / N)? _ N
As requested, no further attempts are made.
Bottom line: web server has not started.
Your code has several odd designs. Bash should generally not need to use expr at all (the shell has built-in facilities for integer arithmetic and substring matching) and you usually want to avoid explicitly testing $?. I would break this up into functions to "divide and conquer" the problem space.
#!/bin/bash
# Print diagnostics to standard error; include script name
echo "$0: Web server is going to be polled" >&2
status=2
poll () {
local i
for ((i=1; i<=$1; ++i)); do
# Move wait to beginning of loop
if (($i > 1)); then
echo "$0: waiting ..." >&2
sleep 1
fi
echo "$0: Polling Nr. $i" >&2
# Just check
if grep -q '^started$' log; then
# return success
return 0
fi
done
# If we fall through to here, return failure
return 1
}
again () {
while true; do
# Notice read -p for prompt
read -t 5 -p "Do you want to poll again? (J/N)" answer
case "$answer" in
[Jj]*) return 0;;
"") continue;;
*) return 1;;
esac
done
}
while true; do
if poll 3
then
echo "$0: Web server has started" >&2
status=0
else
echo "$0: Web server is not started" >&2
status=1
fi
again || break
done
# Actually return the status to the caller
exit "$status"
The while true loop in the main script could easily be adapted to a for loop just like in the poll function if you want to restrict how many times the user is allowed to restart the polling. I wanted to show two different designs just to exhibit the options available to you.
In a real script, I would probably replace several of the simple if tests with the this || that shorthand. In brief,
this && that || other
is roughly equivalent to
if this; then
that
else
other
fi
with the difference that that if that fails, you will also trigger other in the shorthand case.
Perhaps notice also how ((...)) in Bash is an arithmetic context. The three-place for loop is also a Bash extension.
I'm looking for an alternative with while loop that should retrieve the inputs from one file. Even I failed to interpret this with while true condition, in this case I'm unable to give the variables from a file like (cat filename),
My requirement is to check 100 servers whether they are up or not via a ping test for every 5 minutes and log it some custom location (let's say /tmp/output/out-`date +%F`). And also the same script should delete the same logs after 7 days and max size not exceed 1MB per file size.
while read IP
do
ping -c1 $IP &> /dev/null && echo $IP is up || echo $IP is down
sleep 2
done < IP
Note: to run this script in infinite loop, I'm unable to parse the input as variable from file.
while true
do
...
done < filename
Ideas appreciated :)
Multiple tasks run in parallel:
#!/bin/bash
t=5m # time interval
p=() # pid list
_pingAndLog(){ # $1 is the server ip list
local ip
while :; do
while read -r ip || [[ -n $ip ]]; do
if ping -c1 $ip >/dev/null 2>&1; then
echo "`date +%H:%M`: $ip is up"
else
echo "`date +%H:%M`: $ip is down"
fi >>pingtest-`date +%F`.log
done <"$1" # $1 = ip list
sleep "$t"
done
}
_killOldLog(){
while :; do
# use "-mtime +7" to find old files, 7 days
find . -type f -mtime +7 -name 'pingtest-*\.log' -delete
sleep 24h
done
}
_cleanUp(){
echo kill ${p[#]}
kill ${p[#]}
}
for s in *\.list; do # for each file ip list
[[ "$s" = '*.list' ]] && break # no file found, then quit
_pingAndLog "$s" & p+=($!) # run in background, remember pid
done
_killOldLog & p+=($!)
trap _cleanUp 0 2 3 # 0-exit; 2-interrupt, 3-quit
wait # wait backround jobs; Ctrl-C to exit
Note:
Because logfiles are separated by date, so maybe no need to check their sizes; just delete those that are old.
while sleep "$t"; do .. done is also OK to contruct an endless loop as you required.
I've modify this script so that it can ping in parallel, multiple list of IPs.
As the title suggests I am trying to use bash to ping a server then when it gets a connection it will open Firefox to a page displaying an alarm screen. This will happen after a power down when the computer automatically boots then sometimes can take time to connect to the network. If I set Firefox to start on start-up then sometimes it displays the no connection screen.
Here is what I have already, but it does not seem to stop after a successful ping's.
#!/bin/bash
success=0
ping hercules
while [ $success -ne 1 ]; do
ping -c 4 hercules
if [ $? -eq 0 ]; then
success=0
/usr/bin/firefox
else
success=1
fi
done
I am sure I am doing something pretty stupid and this should no be that hard.
Just to fix your script, you can simply exit the script on success:
#!/bin/bash
while true ; do
if ping -c 4 hercules ; then
/usr/bin/firefox
exit 0
fi
done
If I understand your question correctly, what you want is to keep pinging. When it succeeds, to start firefox, and stop pinging? You are currently setting success=1 when it fails, and then exiting the while loop, as success -ne 1 is false.
#!/bin/bash
success=0
ping hercules
while [ $success -ne 1 ]; do
ping -c 4 hercules
if [ $? -eq 0 ]; then
success=1
/usr/bin/firefox
fi
done
#!/bin/bash
ping -t 1 8.8.8.8 #(-t on mac / else it -w)
SUCCESS=0
RETVAL=$?
while [ $SUCCESS -ne 1 ]; do
if [ $RETVAL -eq 0 ]; then
SUCCESS=1
'LAUNCH FIREFOX HERE IF THE PING WORKS'
else
'DO SOMETHING'
fi
done
I am currently using a Raspberry PI as a ping server and this is the script that I am using checking for a ok response.
I'm not familiar with bash scripting so it's a bit of a beginner question with the curl call, is there a way to increase the timeout, as it keeps reporting false down websites.
#!/bin/bash
SITESFILE=/sites.txt #list the sites you want to monitor in this file
EMAILS=" " #list of email addresses to receive alerts (comma separated)
while read site; do
if [ ! -z "${site}" ]; then
CURL=$(curl -s --head $site)
if echo $CURL | grep "200 OK" > /dev/null
then
echo "The HTTP server on ${site} is up!"
sleep 2
else
MESSAGE="This is an alert that your site ${site} has failed to respond 200 OK."
for EMAIL in $(echo $EMAILS | tr "," " "); do
SUBJECT="$site (http) Failed"
echo "$MESSAGE" | mail -s "$SUBJECT" $EMAIL
echo $SUBJECT
echo "Alert sent to $EMAIL"
done
fi
fi
done < $SITESFILE
Yes, man curl:
--connect-timeout <seconds>
Maximum time in seconds that you allow the connection to the server to take.
This only limits the connection phase, once curl has connected this option is
of no more use. See also the -m, --max-time option.
You can also consider using ping to test the connection before calling curl. Something with a ping -c2 will give you 2 pings to test the connection. Then just check the return from ping (i.e. [[ $? -eq 0 ]] means ping succeeded, then connect with curl)
Also you can use [ -n ${site} ] (site is set) instead of [ ! -z ${site} ] (site is not-unset). Additionally, you will generally want to use the [[ ]] test keywords instead of single [ ] for test constructs. For ultimate portability, just use test -n "${site}" (always double-quote when using test.
I think you need this option --max-time <seconds>
-m/--max-time <seconds>
Maximum time in seconds that you allow the whole operation to take. This is useful for preventing your batch jobs from hanging for hours
due to slow networks or links going down.
--connect-timeout <seconds>
Maximum time in seconds that you allow the connection to the server to take. This only limits the connection phase, once curl has connected this option is of no more use.
I'm not sure it should be in stackoverflow or serverfault. I post here because it may be a programming problem.
I have this infinite loop:
#!/bin/bash
MESSAGE="XXX0"
RESULT=`curl "http://somepage.php?thread=0"`
while :
do
if [[ "$RESULT" == "DONE" ]]
then
RESULT=`curl "http://somepage.php?thread=0"`
elif [[ "$RESULT" == "NONE" ]]
then
sleep 5
RESULT=`curl "http://somepage.php?thread=0"`
else
printf "%s %s\n" "$(date --rfc-3339='seconds'): ELSE1-" "$RESULT" >> /var/log/XXX/loopXXX-`date --rfc-3339='date'`
sleep 5
RESULT=`curl "http://somepage.php?thread=0"`
if [[ "$RESULT" == "DONE" ]]
then
RESULT=`curl "http://jsomepage.php?thread=0"`
elif [[ "$RESULT" == "NONE" ]]
then
sleep 5
RESULT=`curl "http://somepage.php?thread=0"`
else
printf "STOP"
break
fi
fi
done
I have 3 loops doing the same job and requesting thread 0 to 2. In the DBtable the PHP page request, there is a column thread. So the three loops query the same table (read/write) but never the same lines.
The problem I experience is that in some nights (almost no activity), one loop doesn't request a page for several hours (I checked in NGINX access log). This only happen sometimes and the server is way more powerfull than needed yet.
Is there problems using infinite loop with curl? In total I have around 10 loops (different pages/tables) but they have a 10s sleep instead of 5s.
Is there a problem in my script with memory/curl? Have you ever experienced something similar?
THanks!
One of the curl lines is probably taking much longer than you expect to execute.
You should use curl's --max-time parameter in order to limit the duration of any single execution to something sane. It expects seconds.
e.g.
RESULT=`curl --max-time 10 "http://somepage.php?thread=0"`
Note that you may now encounter failures where instead you had been seeing long delays. Checking the output might be satisfactory for your application, but return codes are the path to enlightenment. You may even want to use the "-e" option in your shebang and/or create a handler to be used with a trap for ERR.
Try to set max timeouts for your every curl command to prevent them from hanging. Example:
curl -m 50 ...