Im writing a bash script that detects when connection to the internet has dropped and attempts to reconnect as well as displaying status on leds.
Im using the netcat command to connect to google on port 80 to determine if network connection is live
This all works fine when internet is connected, however, when powering off my router (simulating dropout) the netcast command takes aroud 30 seconds to timeout!
Application is for a WiFi radio,
#!/bin/bash
sig_state=0
echo "Network Watchdog ON"
echo "0" > /sys/class/gpio/export
echo "out" > /sys/class/gpio/gpio0/direction
function sig_led_high
{
echo "0" > /sys/class/gpio/gpio0/value
sig_state=1
}
function sig_led_low
{
echo "1" > /sys/class/gpio/gpio0/value
sig_state=0
}
sig_led_low
while true ; do
echo "Testing nwrk..."
if nc -z -w 1 www.google.co.uk 80 > /dev/null 2>&1; then
echo "Network OK. (nwd)"
if ((sig_state)); then
sig_led_low
fi
else
if !((sig_state)); then
sig_led_high
fi
echo "Network connection down! Attempting reconnection."
ifup --force wlan0 > /dev/null 2>&1
if nc -zw1 www.google.co.uk 80 > /dev/null 2>&1; then
mpc play
fi
fi
sleep 1
done
Related
I have task to create quite complicated bash script, which at first part is checking the connection to host:port with telnet and- if telnet would fail or would not be installed, try the connection using netcat.
I have problem with loop, where it will skip netcat if telnet would connect to the host and also, if both- telnet and netcat would fail- script would finish with error message.
The script:
#!/bin/bash
echo Type host IP address
read REMOTEHOST
echo Type port number
read REMOTEPORT
TIMEOUT=5
echo quit | timeout --signal=9 5 telnet $REMOTEHOST $REMOTEPORT
if nc -w $TIMEOUT -z $REMOTEHOST $REMOTEPORT; then
echo "I was able to connect to ${REMOTEHOST}:${REMOTEPORT}"
else
echo "Connection to ${REMOTEHOST}:${REMOTEPORT} failed. Exit code from Netcat was ($?)."
fi
You can use the $? variable to get the exit code from the last command.
I found that your original telnet command exits with error code 1 on my system because the escape character is ^]. When I telnet manually I need to hit ctrl-] to enter the telnet prompt, then I can enter 'quit'.
The trick here is you cannot just type ^], you have to type ctrl-v ctrl-]
ctrl-v tells the system to capture the next ctrl character.
The following gives me an exit code of 0, and you can verify by running it manually with echo $? at the command line
-- remember to use ctrl-v ctr-]
$ (echo ^]; echo quit) | timeout --signal=9 5 telnet <REMOTEHOST> <REMOTEPORT>
$ echo $?
Then you can use this in your script:
#!/bin/bash
echo Type host IP address
read REMOTEHOST
echo Type port number
read REMOTEPORT
TIMEOUT=5
(echo ^]; echo quit) | timeout --signal=9 5 telnet $REMOTEHOST $REMOTEPORT > /dev/null 2>&1
TELNET_EXIT_CODE=$?
if [[ $TELNET_EXIT_CODE -ne 0 ]]; then
nc -w $TIMEOUT -z $REMOTEHOST $REMOTEPORT > /dev/null 2>&1
NC_EXIT_CODE=$?
fi
if [[ $TELNET_EXIT_CODE -eq 0 ]] || [[ $NC_EXIT_CODE -eq 0 ]]; then
echo "success"
else
echo "fail"
fi
Tested on Ubuntu 20.04.04, GNU bash version 5.0.17, Telnet version 0.17-41
How to wire linux shell (sh) script to test with ping if host is reachable?
I guess there could be solution that uses grep but maybe ping provides that option by itself?
I am more into getting a whitelisting a successful ping operation that reached the host then checking if there was any error. I don't care about the reason of ping not succeeding in reaching a host.
I would like to limit ping attempts count and maximum amount of time to reach the host so the script does not waits too long for ping trying to reach a host.
dt=$(date +%d)
cksize=50
echo "Start $(date)"
while IFS= read -r sn
do
echo "*************************************************"
echo "Begin checking NODES client: $sn"
if ping -c 1 "$sn" -i 5 > /dev/null
then
echo "$sn node up"
else
echo "$sn node down"
fi
done < server_list
parallel -j0 --timeout 15 'ping -c 5 -i 0.2 {} >/dev/null 2>&1 && echo {} up || echo {} down' ::: freenetproject.org debian.org no-such.domain {1..254}.2.3.4
You can do it like this. It will do it in parallel for all hosts.
#!/bin/bash
for server in 'google.com' 'github.com' 'fakeserver.com'
do
{ ping -o "$server" &>/dev/null && echo "$server is UP" || echo "$server is DOWN" ; } &
done
wait
Regards!
ip="192.168.129."
function addToList(){
list="$list $1"
}
addToList $1
for i in $ip{$list}
do
ping -c 1 $ip$1 > /dev/null
echo "Ping Status of $ip$1 : Success" ||
echo "Ping Status of $ip$1 : Failed"
done
How can i ping more than one host at the same time and show it in a list which ip address is up or down?
One way is to use a more powerful ping tool like fping.
The other approach is to run the pings in the background:
for ip in $*; do
if [[ "$ip" =~ "^[0-9]+$" ]]; then
ip="192.168.129.$ip"
fi
(
ping -c 1 $ip > /dev/null
if [ $? -eq 0 ]; then
echo "node $ip is up"
else
echo "node $ip is down"
fi
)&
done
(...)& runs a script in the background.
Here is a script I wrote after reading a similar post.
https://bitbucket.org/kurtjensen/nettest/src/master/
It can use multiple text files as possible configs and the config files give you a chance to name the ip address more descriptively. The example config files are
home.txt - Which is the default
momdad.txt - This is for my parents network
etc.
So I can run the script at home and just hit enter at the prompt or enter something like "momdad" to switch to a different config fo a different network.
I have a code which detects if OpenVPN connection is up or down:
if echo 'ifconfig tun0' | grep -q "00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00"
then
echo "VPN up"
else
echo "VPN down"
fi
exit 0
now I'm trying to re-write the code to work with PPTP or IPSEC connection. I've tried to do:
if echo 'ifconfig ppp0' | grep -q "00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00"
or the same with ipsec but does not work. Is there any other way to detect PPTP or IPSEC connection?
That echo statement is erroneous. As #unwind says, the single quotes (') should be backtics (`). Your current code is sending the literal value ifconfig ppp0 to grep, which doesn't do anything useful.
But you don't actually need the backtics, either. You can just send the output of ifconfig to grep directory; using echo doesn't get you anything:
if ifconfig ppp0 | grep -q "00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00"; then
echo ppp connection is up
fi
The following script will:
Run the ISPConnectivity.sh script every 5 minutes. This will mean that the VPN tunnel will not be down for more than 5 minutes.
Check if the tun interface is down, and start the vpn script if it is.
Check connectivity if the tun0 interface is up. It does ping tests on 2 Public IPs (if I get even a single response from 1 of the IPs tested, I consider this a success ), and all have to fail to run the vpn script. I ran ping tests on multiple hosts to prevent the vpn script from starting in case the ping test failed on 1 IP.
Send all failure output to a file in my home directory. I do not need to see if any test succeeded.
Contents of sudo crontab:
*/5 * * * * /home/userXXX/ISPConnectivity.sh >> /home/userXXX/ISPConnectivity.log 2>&1
Contents of ISPConnectivity.sh script:
#!/bin/bash
# add ip / hostname separated by white space
#HOSTS="1.2.3.4"
HOSTS="8.8.8.8 4.2.2.4"
# no ping request
totalcount=0
COUNT=4
DATE=`date +%Y-%m-%d:%H:%M:%S`
if ! /sbin/ifconfig tun0 | grep -q "00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00"
then
echo $DATE tun0 down
sudo /home/userXXX/startVPN.sh start
else
for myHost in $HOSTS;
do
count=`ping -c $COUNT $myHost | grep 'received' | awk -F',' '{ print $2 }' | awk '{ print $1 }'`
totalcount=$(($totalcount + $count))
done
if [ $totalcount -eq 0 ]
then
echo $DATE $totalcount "fail"
sudo /home/userXXX/startVPN.sh start
#else
# echo $DATE $totalcount "pass"
fi
fi
You can also check with the nmcli command, to check if VPN is running or not.
nmcli c show --active | grep vpn
I'm actually looking into more flexible solution eg:
MyIP=$(curl http://api.ipify.org/?format=text)
if [ "$MyIP" != "MYORYGINALIP" ]
then
echo "IPSEC VPN is Running - " $MyIP
else
echo "IPSEC VPN is Not Running - " $MyIP
fi
exit 0
what about that? can I improve it any way?
ip route list table 220 if Ip address shown -> VPN connection established, none -> no VPN
or
if [ "0" == ifconfig | grep wlan0 | wc -l ]; then echo "NO wlan0 has no VPN"; else echo "YES wlan0 has VPN"; fi
Any idea how to create a script in order to test connectivity with IP that represents a default gateway. And in case of connectivity, to print the message "Default gateway up" and if it's not connected to give a message "Default gateway down"
#!/bin/bash
ping -c 1 192.168.1.1 2>&1 > /dev/null
if [ $? -ne 0 ]
then
echo -e "host does not respond to ping"
fi
Put this script in crontab and let it run every min or whatever frequency you want.