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 (a server run by Google).

if ping -q -c 1 -W 1 >/dev/null; then
  echo "IPv4 is up"
  echo "IPv4 is down"

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"
  echo "The network is down"

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";;
  • You may want to incorporate validation of a physical connection (OSI layer 1) prior to any OSI layer 3 checks using ethtool; $ ethtool <dev> | awk '$0 ~ /link detected/{print $3}'
    – jas-
    May 6 '18 at 2:46
  • Can you explain the purpose of adding this please >/dev/null Aug 24 '18 at 9:09
  • @AmineHarbaoui – >/dev/null redirects standard output to /dev/null, the null device, which disposes of it since it is not desired in this case (all we care about is the exit values of the commands). Instead, more applicable output is taken from the echo lines.
    – Adam Katz
    Jan 5 '19 at 16:37

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"

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:

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 }'
  echo "we have connectivity"

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.

  • 6
    I respect Gillies however this is the right answer.
    – gwillie
    Jul 23 '15 at 5:32
  • 3
    add -d e.g. nc -dzw1 also so it doesn't listen for STDIN and hang indefinetily in a script. and maybe use instead of google.com to save a lookup. nc -dzw1 443
    – dza
    Feb 17 '17 at 13:45
  • 1
    @dezza – -w 1 still costs a second when there is no connectivity, though perhaps your nc has some kind of obscure issue somwehere. If you have a recent version of nmap installed, you can instead do ncat --send-only --recv-only -w 334ms to cut that failure time to a third of nc (I've found that 334ms is a good wait time).
    – Adam Katz
    Feb 24 '17 at 19:39
  • 1
    @dezza – I do not know why that is happening to you on both nmap's ncat and netcat (nc) for that system. There might be something odd happening in your network or on that BSD system. Feel free to create a new unix.stackexchange question and get more than just my eyes on that problem. If you do, please link it in comments here and link this thread to your new question.
    – Adam Katz
    Feb 27 '17 at 18:27
  • 1
    @dezza a bit late... but fyi the timeout "not working/the script freezing" appears to be a bug in nc. See this link stackoverflow.com/a/26872879/957573 The timeout didn't work for me either in macOS 10.13.4, and i had to install "gnu netcat 0.7.1" with Homebrew, to work around this.
    – Motsel
    Apr 28 '18 at 20:58

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)


GW=`/sbin/ip route | awk '/default/ { print $3 }'`
checkdns=`cat /etc/resolv.conf | awk '/nameserver/ {print $2}' | awk 'NR == 1 {print; exit}'`

#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;
    echo "Port scan of $checkdomain port 80 failed."

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 ]
      tput setaf 2; echo && echo "$checkdomain pingable. Internet connection is most probably available."&& echo ; tput sgr0;
      #Insert any command you like here
      echo && echo "Could not establish internet connection. Something may be wrong here." >&2
      #Insert any command you like here
#      exit 1

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 ]
      tput setaf 6; echo && echo "$checkdns pingable. Proceeding with domain check."; tput sgr0;
      #Insert any command you like here
      echo && echo "Could not establish internet connection to DNS. Something may be wrong here." >&2
      #Insert any command you like here
#     exit 1

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;;
#  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

ping $GW -c 4

if [ $? -eq 0 ]
  tput setaf 6; echo && echo "LAN Gateway pingable. Proceeding with internet connectivity check."; tput sgr0;
  exit 0
  echo && echo "Something is wrong with LAN (Gateway unreachable)"

  #Insert any command you like here
#  exit 1
  • Nice ! Thank you ! What should we set gateway $GW to ? Jun 8 '17 at 9:45
  • 1
    @CiprianTomoiaga No need, /sbin/ip route | awk '/default/ { print $3 }' gets the gateway address from the (hopefully) primary interface. If you want, you may set the gateway IP address yourself.
    – Aloha
    Dec 4 '17 at 10:28
  • Thanks for this! What I miss though is the option to store internet disruptions in a txt file and an automated email to my ISP.
    – rhand
    Oct 2 '18 at 1:57

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


  • 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.


# 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

TEST=""       # TEST PING

# Report

# 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() {
    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
        echo "================================================================================" >> ${LOGFILE}
        echo "$MESSAGE3 - $TODAY"                                                               >> ${LOGFILE}
        echo "$MESSAGE3 - $TODAY"
        echo "================================================================================" >> ${LOGFILE}
        sleep 10
        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

pastebin: https://pastebin.com/wfSkpgKA

  • What would make this answer better: (1) Explaining how the script works.  (It looks like the user has to edit the script if his network interface is called anything other than eth0, but this is not mentioned.)  (2) Using English.  (3) Putting all shell variables (e.g., "$HOST", "$LINE1" and "$LOG") into double quotes.  (4) Either set LINE2 or don’t use it.  (I suspect that you got LINE1 / LINE2 confused with inet4 / inet6.) … (Cont’d) Dec 4 '17 at 4:02
  • (Cont’d) …  (5) Actually displaying the current time when you say you are displaying the current time, rather than capturing the time when the script starts and displaying it throughout the lifetime of the script.  (6) I think there was something else, but I don’t see it now. Dec 4 '17 at 4:02
  • It is in Spanish because it is in my language, but I can correct it in English. The $ HOST is the address to try. $ LINE1 is the Internet connection that is connected by the eth0 adapter. $ LINE2 is the Internet connection that is connected by the eth1 adapter optionally if you have 2 Internet lines, but it is recommended that you leave it disabled. The date, if I verify that it maintains the same time and date since I start the script, I have to correct that problem. This weekend I correct the problem. Dec 5 '17 at 21:32
  • Ok G-Man, I made some changes, I still need to correct date and improve some things. Jan 5 '18 at 8:21

I am using the following script:


_beep() {
  ( \speaker-test --frequency 400 --test sine -l 1 -p 1 -P 2 >& /dev/null )& # pink / wav
  \sleep 0.5s
  \kill -9 $pid 
  \wait $pid 2>/dev/null

while [ true ]; do
if ! ping -c1 -W 2 google.com >& /dev/null; then
    echo "No internet..."
    if [[ $con -ne 1 ]]
        echo "Connected."
    sleep 1


Here, I am declaring a function beep that is getting called when the ping to the Google server is failing.


@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 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 brd 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 
        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 
        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}'


If there is a link:

root@srv:~# ethtool eno1 | grep "ink detected" | awk '{print $3}'

If there is not a link:

root@srv:~# ethtool rename3 | grep "ink detected" | awk '{print $3}'

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:


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

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 or ask your own question.