networking - Shell Scripting: Proper way to check for internet connectivity? - U...
source link: https://unix.stackexchange.com/questions/190513/shell-scripting-proper-way-to-check-for-internet-connectivity
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Shell Scripting: Proper way to check for internet connectivity?
By using our site, you acknowledge that you have read and understand our Cookie Policy, Privacy Policy, and our Terms of Service.
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems. It only takes a minute to sign up.
I found scripts that say they check for internet connectivity. Some check the IP address if the interface is up BUT it does not check for internet connectivity. I found some that uses ping like this: if [ 'ping google.com -c 4 | grep time' != "" ]; then
but sometimes this may be unreliable as ping itself may hang for some reason (e.g. waiting for some stuck IO).
Any suggestions on the proper/reliable way to check for internet connectivity using scripts? Do I have to use some packages?
It needs to be able to check periodically with cron
for example, then, do something when the connection goes down like invoke ifup --force [interface]
Testing IPv4 connectivity
If your network lets pings through, try pinging 8.8.8.8 (a server run by Google).
if ping -q -c 1 -W 1 8.8.8.8 >/dev/null; then
echo "IPv4 is up"
else
echo "IPv4 is down"
fi
Testing IP connectivity and DNS
If you only want the test to succeed when DNS is also working, use a host name.
if ping -q -c 1 -W 1 google.com >/dev/null; then
echo "The network is up"
else
echo "The network is down"
fi
Testing web connectivity
Some firewalls block pings. Some places have a firewall that blocks all traffic except via a web proxy. If you want to test web connectivity, you can make an HTTP request.
case "$(curl -s --max-time 2 -I http://google.com | sed 's/^[^ ]* *\([0-9]\).*/\1/; 1q')" in
[23]) echo "HTTP connectivity is up";;
5) echo "The web proxy won't let us through";;
*) echo "The network is down or very slow";;
esac
I highly recommend against using ping
to determine connectivity. There are too many network admins that disable ICMP (the protocol it uses) due to worries about ping flood attacks originating from their networks.
Instead, I use a quick test of a reliable server on a port you can expect to be open:
if nc -zw1 google.com 443; then
echo "we have connectivity"
fi
This uses netcat (nc
) in its port scan mode, a quick poke (-z
is zero-I/O mode [used for scanning]) with a quick timeout (-w 1
waits at most one second, though Apple OS X users may need to use -G 1
instead). It checks Google on port 443 (HTTPS).
I've used HTTPS rather than HTTP as an effort to protect against captive portals and transparent proxies which can answer on port 80 (HTTP) for any host. This is less likely when using port 443 since there would be a certificate mismatch, but it does still happen.
If you want to proof yourself against that, you'll need to validate the security on the connection:
test=google.com
if nc -zw1 $test 443 && echo |openssl s_client -connect $test:443 2>&1 |awk '
handshake && $1 == "Verification" { if ($2=="OK") exit; exit 1 }
$1 $2 == "SSLhandshake" { handshake = 1 }'
then
echo "we have connectivity"
fi
This checks for a connection (rather than waiting for openssl to time out) and then makes the SSL handshake, keying on the verification phase. It silently exits ("true") if the verification was "OK" or else exits with an error ("false"), then we report the finding.
I made a script that uses multiple ways to check internet connection (ping, nc, and curl, thanks to Adam Katz, Gilles, and Archemar). I hope someone finds this useful. Feel free to edit it to your liking/optimize it.
Checks your gateway, DNS, and internet connection (using curl, nc, and ping).
Put this in a file then make it executable (Usually sudo chmod +x filename
)
#!/bin/bash
GW=`/sbin/ip route | awk '/default/ { print $3 }'`
checkdns=`cat /etc/resolv.conf | awk '/nameserver/ {print $2}' | awk 'NR == 1 {print; exit}'`
checkdomain=google.com
#some functions
function portscan
{
tput setaf 6; echo "Starting port scan of $checkdomain port 80"; tput sgr0;
if nc -zw1 $checkdomain 80; then
tput setaf 2; echo "Port scan good, $checkdomain port 80 available"; tput sgr0;
else
echo "Port scan of $checkdomain port 80 failed."
fi
}
function pingnet
{
#Google has the most reliable host name. Feel free to change it.
tput setaf 6; echo "Pinging $checkdomain to check for internet connection." && echo; tput sgr0;
ping $checkdomain -c 4
if [ $? -eq 0 ]
then
tput setaf 2; echo && echo "$checkdomain pingable. Internet connection is most probably available."&& echo ; tput sgr0;
#Insert any command you like here
else
echo && echo "Could not establish internet connection. Something may be wrong here." >&2
#Insert any command you like here
# exit 1
fi
}
function pingdns
{
#Grab first DNS server from /etc/resolv.conf
tput setaf 6; echo "Pinging first DNS server in resolv.conf ($checkdns) to check name resolution" && echo; tput sgr0;
ping $checkdns -c 4
if [ $? -eq 0 ]
then
tput setaf 6; echo && echo "$checkdns pingable. Proceeding with domain check."; tput sgr0;
#Insert any command you like here
else
echo && echo "Could not establish internet connection to DNS. Something may be wrong here." >&2
#Insert any command you like here
# exit 1
fi
}
function httpreq
{
tput setaf 6; echo && echo "Checking for HTTP Connectivity"; tput sgr0;
case "$(curl -s --max-time 2 -I $checkdomain | sed 's/^[^ ]* *\([0-9]\).*/\1/; 1q')" in
[23]) tput setaf 2; echo "HTTP connectivity is up"; tput sgr0;;
5) echo "The web proxy won't let us through";exit 1;;
*)echo "Something is wrong with HTTP connections. Go check it."; exit 1;;
esac
# exit 0
}
#Ping gateway first to verify connectivity with LAN
tput setaf 6; echo "Pinging gateway ($GW) to check for LAN connectivity" && echo; tput sgr0;
if [ "$GW" = "" ]; then
tput setaf 1;echo "There is no gateway. Probably disconnected..."; tput sgr0;
# exit 1
fi
ping $GW -c 4
if [ $? -eq 0 ]
then
tput setaf 6; echo && echo "LAN Gateway pingable. Proceeding with internet connectivity check."; tput sgr0;
pingdns
pingnet
portscan
httpreq
exit 0
else
echo && echo "Something is wrong with LAN (Gateway unreachable)"
pingdns
pingnet
portscan
httpreq
#Insert any command you like here
# exit 1
fi
there are many IPs on internet, a light approach is to ping some of them
if ping -c 4 google.com ; then OK ; else KO ; fi
if ping -c 4 facebook.com ; then OK ; else KO ; fi
if ping -c 4 nsa.gov ; then OK ; else KO ; fi # <- this one might not reply
a more complete answer might be getting pages using wget
wget google.com -o google.txt
if parse google.txt ; then OK ; else KO ; fi
where
- parse is a program you write that ensure google.txt is not a (too old) cached version of google.com
thanks to your contributions from each user and other web, I managed to complete this script in 3 days. and I will leave it free for its use.
this script automates the renewal of the ip address when connection is lost, it does so persistently.
#!/bin/bash
# Autor: John Llewelyn
# FB: fb.com/johnwilliam.llewelyn
# Twitter: twitter.com/JWLLEWELYN
# TLF: +584-1491-011-15
# Its use is free.
# Description: Connection Monitor for ADSL modem.
# Requirements:
# Copy this code or save to /home/administrator/ConnectionMonitor.sh
# It requires the installed packages fping beep and cron
# Comment the blacklist pcspkr snd-pcsp in /etc/modprobe.d/blacklist.conf
# Give execute permissions: chmod +x /home/administrator/ConnectionMonitor.sh
# Add this line in crontab -e with root user
# @reboot sleep 120 && /home/administrator/MonitorDeConexion.sh
#################################################################################
# SETTINGS
TEST="8.8.8.8" # TEST PING
ADAPTER1="enp4s0" # EXTERNAL ETHERNET ADAPTER
# Report
LOGFILE=/home/administrator/Documentos/ReportInternet.log
# Messages
MESSAGE1="Restoring Connectivity..."
MESSAGE2="Wait a moment please..."
MESSAGE3="No Internet connectivity."
MESSAGE4="Yes, there is Internet connectivity."
#################################################################################
# Time and Date
TODAY=$(date "+%r %d-%m-%Y")
# Show IP Public Address
IPv4ExternalAddr1=$(ip addr list $ADAPTER1 |grep "inet " |cut -d' ' -f6|cut -d/ -f1)
IPv6ExternalAddr1=$(ip addr list $ADAPTER1 |grep "inet6 " |cut -d' ' -f6|cut -d/ -f1)
# Alarm
alarm() {
beep -f 1500 -l 200;beep -f 1550 -l 200;beep -f 1500 -l 200;beep -f 1550 -l 200;beep -f 1500 -l 200;beep -f 1550 -l 200;beep -f 1500 -l 200;beep -f 1550$
}
# Restoring Connectivity
resolve() {
clear
echo "$MESSAGE1"
sudo ifconfig $ADAPTER1 up;sudo dhclient -r $ADAPTER1;sleep 5;sudo dhclient $ADAPTER1
echo "$MESSAGE2"
sleep 120
}
# Execution of work
while true; do
if [[ "$(fping -I $ADAPTER1 $TEST | grep 'unreachable' )" != "" ]]; then
alarm
clear
echo "================================================================================" >> ${LOGFILE}
echo "$MESSAGE3 - $TODAY" >> ${LOGFILE}
echo "$MESSAGE3 - $TODAY"
echo "================================================================================" >> ${LOGFILE}
sleep 10
resolve
else
clear
echo "================================================================================" >> ${LOGFILE}
echo "$MESSAGE4 - $TODAY - IPv4 Addr: $IPv4ExternalAddr1 - IPv6 Addr: $IPv6ExternalAddr1" >> ${LOGFILE}
echo "$MESSAGE4 - $TODAY - IPv4 Addr: $IPv4ExternalAddr1 - IPv6 Addr: $IPv6ExternalAddr1"
echo "================================================================================" >> ${LOGFILE}
sleep 120
fi
done
pastebin: https://pastebin.com/wfSkpgKA
@PNDA suggested getting data from ethtool, which I like. But, I prefer piping to grep and using a more simple awk command that non-bash people can figure out faster. The time difference between the two is negligible.
Using: Ubuntu Bionic 18.04
Network interface discovery:
root@srv:~# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eno1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 00:1e:67:96:a3:97 brd ff:ff:ff:ff:ff:ff
inet 10.0.1.101/8 brd 10.255.255.255 scope global eno1
valid_lft forever preferred_lft forever
inet6 fe80::21e:67ff:fe96:a397/64 scope link
valid_lft forever preferred_lft forever
3: rename3: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
link/ether 00:1e:67:96:a3:96 brd ff:ff:ff:ff:ff:ff
ethtool output:
root@srv:~# ethtool eno1
Settings for eno1:
Supported ports: [ TP ]
Supported link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Supported pause frame use: No
Supports auto-negotiation: Yes
Supported FEC modes: Not reported
Advertised link modes: 10baseT/Half 10baseT/Full
100baseT/Half 100baseT/Full
1000baseT/Full
Advertised pause frame use: No
Advertised auto-negotiation: Yes
Advertised FEC modes: Not reported
Speed: 1000Mb/s
Duplex: Full
Port: Twisted Pair
PHYAD: 1
Transceiver: internal
Auto-negotiation: on
MDI-X: on (auto)
Supports Wake-on: pumbg
Wake-on: g
Current message level: 0x00000007 (7)
drv probe link
Link detected: yes
Command example:
ethtool eno1 | grep "ink detected" | awk '{print $3}'
Choose your own adventure:
ethtool {{network adapter}} | grep "ink detected" | awk '{print $3}'
Output:
If there is a link:
root@srv:~# ethtool eno1 | grep "ink detected" | awk '{print $3}'
yes
If there is not a link:
root@srv:~# ethtool rename3 | grep "ink detected" | awk '{print $3}'
no
If you want to avoid false positives due to the presence of a Captive Portal you'll have to check the output of an HTTP connection against a website of predictable content/answer.
Something like this:
#!/bin/sh
detection_out=$(wget -q http://detectportal.firefox.com/success.txt --timeout=10 -O - 2> /dev/null)
test "$detection_out" = "success"
exit $?
This checks if the content of http://detectportal.firefox.com/success.txt is exactly identical to success
.
The output is provided as an exit code: if the exit code is zero, the connection is available, otherwise it is either not available for some reason or blocked by a captive portal.
I took this script from here: https://github.com/libremesh/lime-packages/pull/712/files
Your Answer
Post as a guest
Required, but never shown
By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy
Not the answer you're looking for? Browse other questions tagged shell-script networking internet or ask your own question.
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK