Bash continue only if ping is down - linux

I'm trying to create a script which will only continue when pinging is unresponsive.
I'm running into 2 main issues. One being that it will require 2 CTL-C commands to end the script, and the other issue being that the script will never end and will need killing.
Here are my attempts;
rc=0
until [ $rc -gt 0 ]
do
ping 69.69.69.69 > /dev/null 2>&1
rc=$?
done
## Here will be the rest of code to be executed
I feel this one above is very close as it requires the 2 CTL-C commands and continues.
Here is something I found on SO but can't get to work at all.
counter=0
while [ true ]
do
ping -c 1 69.69.69.69 > /dev/null 2>&1
if [ $? -ne 0 ] then
let "counter +=1"
else
let "counter = 0"
fi
if [ $counter -eq 10 ] then
echo "Here should be executed once pinging is down"
fi
done
Any assistance is greatly appreciated, Thank you.

Try this:
while ping -c 1 -W 20 "$host" >& /dev/null
do
echo "Host reachable"
sleep 10 # do not ping too often
done
echo "Host unreachable within 20 seconds"

There's a few issues with that:
Firstly the if statements are wrong
Use this format
if [ $? -ne 0 ] then;
or this other format
if [ $? -ne 0 ]
then
Secondly I suspect that your pings are not timing out
ping -c 1 -w 2 69.69.69.69 > /dev/null 2>&1
might be helpfull
Thirdly your loop will continue incrementing counter even after 10. You might want to quit after 10
while [ $counter -le 10 ]
If you would be happy with executing something if ping times out after x seconds without any response it could be all condensed (ten seconds in the example below):
ping -c 1 -w 10 69.69.69.69 >/dev/null 2>&1 || echo "run if ping timedout without any response"

Related

Stop a loop process in shell scripting after some time

I have a script that looks like this, this script is checking whether my pods is in Running state or Not by redefining x on every loop.
x=$(/opt/oc get pods --selector app=${bamboo.shortPlanName} -o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
until [ "$x" == "Running" ];
do
sleep 5
x=$(/opt/oc get pods --selector app=${bamboo.shortPlanName} -o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
echo $x
done
But, I want to modify my current script to also support timeout, I mean after 60 second of looping, then it should be stop, or after 12 times of looping, then it should be stop. Any idea how to do that?
bash provides a special variable SECONDS that can be used as a rough timer.
SECONDS=0
while (( SECONDS < 60)); do
x=$(/opt/oc get pods --selector app=${bamboo.shortPlanName} -o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
if [[ $x == Running ]]; then
break
fi
sleep 5
done
The expansion of SECONDS gives you not the assigned value, but the difference between the numbers of seconds since the assignment and the assigned value. The effect is like a variable whose value is incremented by 1 each second.
For timeout after 60 seconds try this Shellcheck-clean code:
#! /bin/bash -p
readonly kOC_SLEEP_SECS=5
readonly kOC_TIMEOUT_SECS=60
initial_secs=$SECONDS
while
status=$(/opt/oc get pods --selector app=bamboo.shortPlanName \
-o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
printf '%s\n' "$status"
[[ $status != Running ]]
do
if (( (SECONDS - initial_secs) >= kOC_TIMEOUT_SECS )); then
echo 'ERROR: Timed out' >&2
exit 1
fi
sleep -- "$kOC_SLEEP_SECS"
done
I replaced app=${bamboo.shortPlanName} with app=bamboo.shortPlanName because the old code was causing Bash errors. You'll need to fix it properly.
See Why is printf better than echo? for an explanation of why I replaced echo with printf for printing the status.
The code treats a timeout as an error, and exits with bad status. You might want to do something different.
The actual timeout period will be somewhere between 60 and 65 (or maybe a little more) seconds. You'll need to do something different if you need a more accurate timeout.
For a timeout after 12 iterations try this Shellcheck-clean variation on the code above:
#! /bin/bash -p
readonly kOC_SLEEP_SECS=5
readonly kOC_MAX_ITERS=12
oc_iters=0
while
status=$(/opt/oc get pods --selector app=bamboo.shortPlanName \
-o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
printf '%s\n' "$status"
[[ $status != Running ]]
do
if (( ++oc_iters >= kOC_MAX_ITERS )); then
echo 'ERROR: Timed out' >&2
exit 1
fi
sleep -- "$kOC_SLEEP_SECS"
done
I think trap is the easiest way to have an accurate timeout.
Prototype:
#! /bin/bash
HALT=0
TIMEOUT=4
# Trap for SIGALRM
stop_loop() {
HALT=1
}
# Set trap
trap stop_loop SIGALRM
# The timeout goes after $TIMEOUT seconds.
{ sleep $TIMEOUT && kill -SIGALRM $$ & }
# Main loop
until false || [[ $HALT -eq 1 ]]; do
sleep 1
echo 'loop'
done
echo 'out of loop'
exit 0
In your case, this looks a something like:
HALT=0
TIMEOUT=4
stop_loop() {
HALT=1
}
trap stop_loop SIGALRM
x=$(/opt/oc get pods --selector app=${bamboo.shortPlanName} \
-o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
{ sleep $TIMEOUT && kill -SIGALRM $$ & }
until [ "$x" == "Running" ] || [[ $HALT -eq 1 ]];
do
sleep 5
x=$(/opt/oc get pods --selector app=${bamboo.shortPlanName} \
-o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
echo $x
done
exit 0

Bash Script not detecting failed exit codes

I can't get my bash script (a logging file) to detect any other exit code other than 0, so the count for failed commands isn't being incremented, but the successes is incremented regardless of whether the command failed or succeeded.
Here is the code:
#!/bin/bash
#Script for Homework 8
#Created by Greg Kendall on 5/10/2016
file=$$.cmd
signal() {
rm -f $file
echo
echo "User Aborted by Control-C"
exit
}
trap signal 2
i=0
success=0
fail=0
commands=0
read -p "$(pwd)$" "command"
while [ "$command" != 'exit' ]
do
$command
((i++))
echo $i: "$command" >> $file
if [ "$?" -eq 0 ]
then
((success++))
((commands++))
else
((fail++))
((commands++))
fi
read -p "$(pwd)" "command"
done
if [ "$command" == 'exit' ]
then
rm -f $file
echo commands:$commands "(successes:$success, failures:$fail)"
fi
Any help would be greatly appreciated. Thanks!
That's because echo $i: "$command" is succeeding always.
The exit status $? in if [ "$?" -eq 0 ] is actually the exit status of echo, the command that is run immediately before the checking.
So do the test immediate after the command:
$command
if [ "$?" -eq 0 ]
and use echo elsewhere
Or if you prefer you don't need the $? check at all, you can run the command and check status within if alone:
if $command; then .....; else ....; fi
If you do not want to get the STDOUT and STDERR:
if $command &>/dev/null; then .....; else ....; fi
** Note that, as #Charles Duffy mentioned in the comment, you should not run command(s) from variables.
Your code is correctly counting the number of times that the echo $i: "$command" command fails. I presume that you would prefer to count the number of times that $command fails. In that case, replace:
$command
((i++))
echo $i: "$command" >> $file
if [ "$?" -eq 0 ]
With:
$command
code=$?
((i++))
echo $i: "$command" >> $file
if [ "$code" -eq 0 ]
Since $? captures the exit code of the previous command, it should be placed immediately after the command whose code we want to capture.
Improvement
To make sure that the value of $? is captured before any other command is run, Charles Duffy suggests placing the assignment on the same line as the command like so:
$command; code=$?
((i++))
echo $i: "$command" >> $file
if [ "$code" -eq 0 ]
This should make it less likely that any future changes to the code would separate the command from the capture of the value of $?.

How to send Internet connectivity alerts using a Bash script?

I have a flaky Internet connection, so I decided to make a bash script that would alert me whenever the internet is back. This is the script:
#!/bin/bash
# set -x
while [ 1 ];do
STATUS_CURRENT=$(ping -q -w 1 -c 1 google.com > /dev/null && echo connected || echo disconnected)
if [[ $STATUS_CURRENT == "connected" && $STATUS_LAST != "connected" ]];then
aplay /home/user/bin/online.wav
notify-send "We've connected"
elif [[ $STATUS_CURRENT == "disconnected" && $STATUS_LAST == "connected" ]];then
aplay /home/user/bin/offline.wav
notify-send "Disconnected now"
fi
STATUS_LAST=$STATUS_CURRENT
sleep 2
done
I have this added in /etc/rc.local to have it executed on startup. The problem with this script is that it sometimes fail. Even when there's Internet connectivity, the script sends notification saying it's disconnected (immediately followed by the "connected" message).
How can I avoid this problem? Does it have something to do with the fact that ping is slow to fail? How can the script be improved?
With "netcat" it works very stable for me
#!/bin/bash
status=0
do_on=("/home/user/bin/online.wav"
"We've connected")
do_off=("/home/user/bin/offline.wav"
"Disconnected now")
while [ 1 ] ;do
nc -zw 2 google.de 80
ret="$?"
if [ "$ret" = 0 -a "$status" = 0 ] ;then
aplay ${do_on[0]}
notify-send ${do_on[1]}
status=1
elif [ "$ret" -ne 0 -a "$status" = 1 ] ;then
aplay ${do_off[0]}
notify-send ${do_off[1]}
status=0 ;fi
sleep 2 ;done
You should test your DNS server in advance
cheers Karim

How to rerun the process if it dies - Linux

Can any one let me know how to re-run the process automatically again if it gets dies. Below is my code which i have tired but it is giving me an error :
Edited Code :
commandpid=`$busyboxValue pidof command`
echo ${commandpid} > /sdcard/CommandProcess.txt
if [ $commandpid -gt 0 ]
then
echo -16 > /proc/$commandpid/oom_adj
echo -1000 > /proc/$commandpid/oom_score_adj
fi
while [ true ]
do
echo "PID $commandpid"
if [ ps -p $commandpid > /dev/null ]
then
echo "[$(date)] :Process is already running with PID $commandpid"
else
echo "[$(date)] :Process is not running"
/data/local/command 1200 &
commandpid=`$busyboxValue pidof command`
echo ${commandpid} > /sdcard/CommandProcess.txt
fi
sleep 10
done
I have updated the code but still with the above code multiple process id i am getting. Dose it mean my else part code is keep executing? If yes the what changes i need to do to stop it?
Can please any one help me ?
To repeatedly run a command, regardless of exit status:
while :; do command; done
To repeatedly run a command until a successful exit:
until command; do :; done

how to check the process is running or not - Linux

I am invoking a binary file using shell script. Binary file is basically establish a socket client server. this binary works fine initially but after 60mints its is getting stop. I need to check if it is not running then start it again. here is my code :
sleep 3
busyboxValue=busybox
commandpid=`$busyboxValue pidof command`
echo ${commandpid} > /sdcard/CommandProcess.txt
if [ $commandpid -gt 0 ]
then
echo -16 > /proc/$commandpid/oom_adj
echo -1000 > /proc/$commandpid/oom_score_adj
fi
while [ true ]
do
commandpid=`$busyboxValue pidof command`
if [ $commandpid -gt 0 ]
then
echo "command binary still running"
else
echo "command binary Exited so restarting it"
/data/local/command 1200 &
commandpid=`$busyboxValue pidof command`
echo ${commandpid} > /sdcard/CommandProcess.txt
echo -16 > /proc/$commandpid/oom_adj
echo -1000 > /proc/$commandpid/oom_score_adj
fi
sleep 10
done
You can use the python supervisor utility, which will take care of re-starting a dead program for you.
https://pypi.python.org/pypi/supervisor

Resources