How can an internet connection be tested without pinging some website? I mean, what if there is a connection but the site is down? Is there a check for a connection with the world?
-
2ping several different sites? – May 30 '09 at 08:46
-
1but I don't want to ping websites, there are no other option? – lauriys May 30 '09 at 08:50
-
6I just want to see that there are maybe other way! – lauriys May 30 '09 at 08:52
-
2There is no better way than sending and receiving a single packet to a set of addresses that you know not to go offline all at once, another way is to check your current set DNS if you don't want your application to ping a more public domain. – Tamara Wijsman May 30 '09 at 09:11
-
@Neil: I can't speak for the original questioner's reasons, but some places block ping. For example, at my workplace I can't ping anything outside my subnet. – PTBNL May 31 '09 at 03:35
-
14I want to know if anyone is listening, without making a sound! – Kaz Mar 23 '12 at 22:15
22 Answers
Without ping
#!/bin/bash
wget -q --spider http://google.com
if [ $? -eq 0 ]; then
echo "Online"
else
echo "Offline"
fi
-q : Silence mode
--spider : don't get, just check page availability
$? : shell return code
0 : shell "All OK" code
Without wget
#!/bin/bash
echo -e "GET http://google.com HTTP/1.0\n\n" | nc google.com 80 > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "Online"
else
echo "Offline"
fi

- 36,288
- 32
- 162
- 271

- 3,418
- 1
- 18
- 15
-
4very nice... but of course assumes the box has wget. embedded devices and whatnot probably won't. ;) – Eric Sebasta Jun 08 '15 at 19:03
-
6Try this: echo -e "GET http://google.com HTTP/1.0\n\n" | nc google.com 80 > /dev/null 2>&1 – user3439968 Jun 16 '15 at 23:46
-
1tcping would also be of help here. ( tcping www.yahoo.com 80 ) && echo "Site is up" – David Ramirez Aug 07 '15 at 15:14
-
The if/else statement use here wirh explanation is great. Thank you ! – Danijel-James W Apr 07 '16 at 01:45
-
2@user3439968 You need to add timeout to `nc` to make sure it times out. something like `nc google.com 80 -w 10` – kaptan Apr 20 '17 at 21:08
-
I tried these on a docker image without `ping` command. `wget` worked fine but `get` always return false (even with internet connection) – Benjamin Jan 31 '18 at 11:10
-
I'm in an environment that has neigher `wget` nor `nc` (git-bash on windows) but it has curl. Could you include the `curl` equivalent of the `wget` answer? in particular, I'm unsure what would be the exact equivalent of `--spider` for curl. Thanks! – Somo S. May 24 '19 at 12:21
-
1It can be solved using pure Bash https://stackoverflow.com/a/56138210/2859065 – Luchostein Dec 11 '21 at 03:13
Ping your default gateway:
#!/bin/bash
ping -q -w 1 -c 1 `ip r | grep default | cut -d ' ' -f 3` > /dev/null && echo ok || echo error

- 5,341
- 2
- 24
- 20
-
14good technique, it can be modified to be used in a function: `function ping_gw() { ... && return 0 || return 1 }` and then used like so: `ping_gw || (echo "no network, bye" && exit 1)` – memnoch_proxy Mar 22 '13 at 13:56
-
Note that on distributions where the `/sbin` directory is not in the default path (like Mageia), one should either add `sudo ` or `/sbin/`before it, like that: `ping -q -w 1 -c 1 \`/sbin/ip r | grep default | cut -d ' ' -f 3\`` – Kleag Dec 18 '14 at 14:41
-
1on mac os this does not work via copy-paste: "-bash: ip: command not found ping: illegal option -- w" – Benedikt S. Vogler Feb 11 '16 at 13:30
-
1Gives a false alarm if run from a virtualization guest while the host is not connected. – admirabilis Mar 26 '17 at 03:50
-
@BenediktS.Vogler [see my answer for a MacOS version](https://stackoverflow.com/a/48229061/395414) – Francisc0 Jan 12 '18 at 15:15
-
Won't this return a false positive if the LAN you're connected to has no internet access? – Ajedi32 Aug 15 '18 at 16:00
-
1
-
2Be careful with this. I just tested this by doing `ifconfig down wlan0` and I still have a default gateway and it is pingable, even though I in fact cannot reach the outside world. – Bruno Bronosky Nov 13 '18 at 19:46
-
I am connected via ethernet and wlan, so I get two entries from `ip r` and the command fails. A good way would probably be to ping both, however I have changed the grep to `grep -m 1 default` to just try the first one and now it returns OK. – Cromon Jan 12 '19 at 11:38
-
-
@Cmag, I highly doubt your default gateway is a website--it's usually your router... OP is saying they don't want to rely on a website (e.g. google.com or facebook.com) being available, perhaps as they could be blocked or masked by many entities (gov't, corp, attacker). So I wouldn't say pinging your default gateway would violate OP's constraint... – johnny Jul 27 '19 at 14:38
-
I get online even after disabling wifi. This can not be reliable. – Pritesh Gohil Aug 02 '20 at 09:16
-
It can be solved using pure Bash https://stackoverflow.com/a/56138210/2859065 – Luchostein Dec 11 '21 at 03:13
-
As noted MacOS doesn't support `-w 1`, though it does support `-t` and `-W` for timeouts. The first in seconds the latter in milliseconds.Other pings support `-W` so we almost have a portable solution that doesn't hang for ages if you're offline ... except `-W` elsewhere is in seconds. – Partly Cloudy Aug 03 '22 at 21:26
Super Thanks to user somedrew for their post here: https://bbs.archlinux.org/viewtopic.php?id=55485 on 2008-09-20 02:09:48
Looking in /sys/class/net should be one way
Here's my script to test for a network connection other than the loop back. I use the below in another script that I have for periodically testing if my website is accessible. If it's NOT accessible a popup window alerts me to a problem.
The script below prevents me from receiving popup messages every five minutes whenever my laptop is not connected to the network.
#!/usr/bin/bash
# Test for network conection
for interface in $(ls /sys/class/net/ | grep -v lo);
do
if [[ $(cat /sys/class/net/$interface/carrier) = 1 ]]; then OnLine=1; fi
done
if ! [ $OnLine ]; then echo "Not Online" > /dev/stderr; exit; fi
Note for those new to bash: The final 'if' statement tests if NOT [!] online and exits if this is the case. See man bash and search for "Expressions may be combined" for more details.
P.S. I feel ping is not the best thing to use here because it aims to test a connection to a particular host NOT test if there is a connection to a network of any sort.
P.P.S. The Above works on Ubuntu 12.04 The /sys may not exist on some other distros. See below:
Modern Linux distributions include a /sys directory as a virtual filesystem (sysfs, comparable to /proc, which is a procfs), which stores and allows modification of the devices connected to the system, whereas many traditional UNIX and Unix-like operating systems use /sys as a symbolic link to the kernel source tree.[citation needed]
From Wikipedia https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard
-
1Careful now!" `cat /sys/class/net/wwan0/carrier` does not work on ubuntu 14.04 LTS. – dotnetCarpenter Mar 01 '15 at 20:45
-
1You may want to put `2>/dev/null` after `cat /sys/class/net/$interface/carrier` to not have error output in case networking is disabled. – jarno Mar 13 '16 at 21:26
This works on both MacOSX and Linux:
#!/bin/bash
ping -q -c1 google.com &>/dev/null && echo online || echo offline

- 2,507
- 3
- 23
- 22
-
-
`fping google.com` or simply `fping 8.8.8.8` does the magic with a bonus you get status code without the need to test it ("`google.com is alive`")... – Roger Apr 19 '19 at 09:48
-
@avishayp It works on macOS' version of ping if you change the timeout argument, using `-t` instead of `-w` — `ping -q -t 1 -c 1 google.com &> /dev/null && echo online || echo offline` – sidneys Jul 10 '21 at 14:30
-
@sidneys I just tried your version on Ubuntu but no good. I also tested the version that is currently published, and no good on MacOSX. If I remove the -w1 then everything works on both platforms, so I'm going with that. – legel Oct 05 '21 at 20:46
-
In Bash, using it's network wrapper through /dev/{udp,tcp}/host/port:
if : >/dev/tcp/8.8.8.8/53; then
echo 'Internet available.'
else
echo 'Offline.'
fi
(:
is the Bash no-op, because you just want to test the connection, but not processing.)

- 2,314
- 20
- 24
-
1
-
1
-
@polendina Maybe add timeout? `timeout 10 true >/dev/tcp/8.8.8.8/53` ? (changes "`:`" by "`true`") – Luchostein Apr 05 '22 at 14:33
-
1`timeout 10 true >/dev/tcp/8.8.8.8/53` still blocked for me, but wrapping the whole command in sh that we want to kill in case of a timeout worked: `timeout 10 sh -c "true >/dev/tcp/8.8.8.8/53"`. This way one can also use `:` instead of `true`. – agostonbarna Oct 19 '22 at 16:07
The top answer misses the fact that you can have a perfectly stable connection to your default gateway but that does not automatically mean you can actually reach something on the internet. The OP asks how he/she can test a connection with the world. So I suggest to alter the top answer by changing the gateway IP to a known IP (x.y.z.w) that is outside your LAN.
So the answer would become:
ping -q -w 1 -c 1 x.y.z.w > /dev/null && echo ok || echo error
Also removing the unfavored backticks for command substitution[1].
If you just want to make sure you are connected to the world before executing some code you can also use:
if ping -q -w 1 -c 1 x.y.z.w > /dev/null; then
# more code
fi

- 121
- 2
- 6
make sure your network allow TCP traffic in and out, then you could get back your public facing IP with the following command
curl ifconfig.co

- 1,296
- 1
- 14
- 15
Execute the following command to check whether a web site is up, and what status message the web server is showing:
curl -Is http://www.google.com | head -1 HTTP/1.1 200 OK
Status code ‘200 OK’ means that the request has succeeded and a website is reachable.

- 2,067
- 2
- 28
- 31
-
2A better implementation could be `curl -Is http://www.google.com | head -1 | grep 200; if [[ $? -eq 0 ]]; then; echo "Online"; else; echo "Offline"; fi;` – Luca Galasso Feb 21 '19 at 10:08
I've written scripts before that simply use telnet to connect to port 80, then transmit the text:
HTTP/1.0 GET /index.html
followed by two CR/LF sequences.
Provided you get back some form of HTTP response, you can generally assume the site is functioning.

- 854,327
- 234
- 1,573
- 1,953
-
3
-
7Because wget and curl aren't always available (e.g., restrictions in corporate environments). Telnet has been a standard part of every UNIX since time t=0. – paxdiablo May 31 '09 at 03:19
-
Yeah, telnetting has been a pretty standard way to test connections for quite a while. – PTBNL May 31 '09 at 03:32
-
2Good point, although wget is fairly common. Another option is netcat (nc), although in this case it's not any improvement over telnet. – Adam Rosenfield May 31 '09 at 04:20
The top voted answer does not work for MacOS so for those on a mac, I've successfully tested this:
GATEWAY=`route -n get default | grep gateway`
if [ -z "$GATEWAY" ]
then
echo error
else
ping -q -t 1 -c 1 `echo $GATEWAY | cut -d ':' -f 2` > /dev/null && echo ok || echo error
fi
tested on MacOS High Sierra 10.12.6

- 968
- 1
- 14
- 28
-
2Change the `route` command to `route -n get default 2> /dev/null | grep gateway` to avoid writing an error to stderr when offline. – devstuff Dec 19 '18 at 19:51
Similarly to @Jesse's answer, this option might be much faster than any solution using ping
and perhaps slightly more efficient than @Jesse's answer.
find /sys/class/net/ -maxdepth 1 -mindepth 1 ! -name "*lo*" -exec sh -c 'cat "$0"/carrier 2>&1' {} \; | grep -q '1'
Explenation:
This command uses find
with -exec
to run command on all files not named *lo*
in /sys/class/net/
. These should be links to directories containing information about the available network interfaces on your machine.
The command being ran is an sh
command that checks the contents of the file carrier
in those directories. The value of $interface/carrier
has 3 meanings - Quoting:
It seems there are three states:
- ./carrier not readable (for instance when the interface is disabled in Network Manager).
- ./carrier contain "1" (when the interface is activated and it is connected to a WiFi network)
- ./carrier contain "0" (when the interface is activated and it is not connected to a WiFi network)
The first option is not taken care of in @Jesse's answer. The sh
command striped out is:
# Note: $0 == $interface
cat "$0"/carrier 2>&1
cat
is being used to check the contents of carrier
and redirect all output to standard output even when it fails because the file is not readable.
If grep -q
finds "1"
among those files it means there is at least 1 interface connected. The exit code of grep -q
will be the final exit code.
Usage
For example, using this command's exit status, you can use it start a gnubiff in your ~/.xprofile
only if you have an internet connection.
online() {
find /sys/class/net/ -maxdepth 1 -mindepth 1 ! -name "*lo*" -exec sh -c 'cat "$0"/carrier 2>&1 > /dev/null | grep -q "1" && exit 0' {} \;
}
online && gnubiff --systemtray --noconfigure &
Reference

- 2,606
- 2
- 21
- 24
This bash script continuously check for Internet and make a beep sound when the Internet is available.
#!/bin/bash
play -n synth 0.3 sine 800 vol 0.75
while :
do
pingtime=$(ping -w 1 8.8.8.8 | grep ttl)
if [ "$pingtime" = "" ]
then
pingtimetwo=$(ping -w 1 www.google.com | grep ttl)
if [ "$pingtimetwo" = "" ]
then
clear ; echo 'Offline'
else
clear ; echo 'Online' ; play -n synth 0.3 sine 800 vol 0.75
fi
else
clear ; echo 'Online' ; play -n synth 0.3 sine 800 vol 0.75
fi
sleep 1
done

- 4,708
- 3
- 24
- 42

- 2,194
- 1
- 18
- 19
If your local nameserver is down,
ping 4.2.2.1
is an easy-to-remember always-up IP (it's actually a nameserver, even).

- 198,619
- 38
- 280
- 391
shortest way: fping 4.2.2.1
=> "4.2.2.1 is alive"
i prefer this as it's faster and less verbose output than ping
, downside is you will have to install it.
you can use any public dns rather than a specific website.
fping -q google.com && echo "do something because you're connected!"
-q
returns an exit code, so i'm just showing an example of running something you're online.
to install on mac: brew install fping
; on ubuntu: sudo apt-get install fping

- 2,913
- 2
- 24
- 22
Checking Google's index page is another way to do it:
#!/bin/bash
WGET="/usr/bin/wget"
$WGET -q --tries=20 --timeout=10 http://www.google.com -O /tmp/google.idx &> /dev/null
if [ ! -s /tmp/google.idx ]
then
echo "Not Connected..!"
else
echo "Connected..!"
fi

- 4,130
- 8
- 35
- 46
For the fastest result, ping a DNS server:
ping -c1 "8.8.8.8" &>"/dev/null"
if [[ "${?}" -ne 0 ]]; then
echo "offline"
elif [[ "${#args[@]}" -eq 0 ]]; then
echo "online"
fi
Available as a standalone command: linkStatus

- 950
- 9
- 16
Ping was designed to do exactly what you're looking to do. However, if the site blocks ICMP echo, then you can always do the telnet to port 80 of some site, wget, or curl.

- 238
- 1
- 3
If your goal is to actually check for Internet access, many of the existing answers to this question are flawed. A few things you should be aware of:
- It's possible for your computer to be connected to a network without that network having internet access
- It's possible for a server to be down without the entire internet being inaccessible
- It's possible for a captive portal to return an HTTP response for an arbitrary URL even if you don't have internet access
With that in mind, I believe the best strategy is to contact several sites over an HTTPS connection and return true if any of those sites responds.
For example:
connected_to_internet() {
test_urls="\
https://www.google.com/ \
https://www.microsoft.com/ \
https://www.cloudflare.com/ \
"
processes="0"
pids=""
for test_url in $test_urls; do
curl --silent --head "$test_url" > /dev/null &
pids="$pids $!"
processes=$(($processes + 1))
done
while [ $processes -gt 0 ]; do
for pid in $pids; do
if ! ps | grep "^[[:blank:]]*$pid[[:blank:]]" > /dev/null; then
# Process no longer running
processes=$(($processes - 1))
pids=$(echo "$pids" | sed --regexp-extended "s/(^| )$pid($| )/ /g")
if wait $pid; then
# Success! We have a connection to at least one public site, so the
# internet is up. Ignore other exit statuses.
kill -TERM $pids > /dev/null 2>&1 || true
wait $pids
return 0
fi
fi
done
# wait -n $pids # Better than sleep, but not supported on all systems
sleep 0.1
done
return 1
}
Usage:
if connected_to_internet; then
echo "Connected to internet"
else
echo "No internet connection"
fi
Some notes about this approach:
- It is robust against all the false positives and negatives I outlined above
- The requests all happen in parallel to maximize speed
- It will return false if you technically have internet access but DNS is non-functional or your network settings are otherwise messed up, which I think is a reasonable thing to do in most cases

- 45,670
- 22
- 127
- 172
-
The return code from curl is not being tested. On my system if the network is not available curl gives rc=6 (failed DNS resolution) but this code still reports "Connected to internet". – ceperman Dec 02 '19 at 11:07
-
@ceperman The return code for curl is tested on the line where it says `if wait $pid;`. No idea why that's not working on your system. Are you sure you're using bash? – Ajedi32 Dec 02 '19 at 12:11
-
@ceperman Another possibility; perhaps one of the URLs in the list at the top actually _does_ return success for you, even though the others are failing name resolution? – Ajedi32 Dec 02 '19 at 12:23
-
2My bash is pretty basic so I read up on `wait` and now understand the return code is indeed being tested. I re-copied your code and today it works - whoops! I must have messed something up last time although I can't understand what or how. Nevertheless, mea culpa. Apologies. – ceperman Dec 03 '19 at 15:46
Pong doesn't mean web service on the server is running; it merely means that server is replying to ICMP echo. I would recommend using curl and check its return value.

- 2,966
- 1
- 16
- 4
If you want to handle captive portals, you can do this oneliner:
if [[ $(curl -s -D - http://www.gstatic.com/generate_204 2>/dev/null | head -1 | cut -d' ' -f 2) == "204" ]]; then
echo 'online'
else
echo 'offline'
fi
Or if you want something more readable that can differentiate captive portals from lack of signal:
function is_online() {
# Test signal
local response
response=$(curl --silent --dump-header - http://www.gstatic.com/generate_204 2> /dev/null)
if (($? != 0)); then return 2; fi
# Test captive portal
local status=$(echo $response | head -1 | cut -d' ' -f 2)
((status == "204"))
}
is_online && echo online || echo offline

- 393
- 4
- 11
In case it helps someone, I do it like this.
It just "retries" until the network is "alive".
You can echo
output here just for POL.
true
or continue
can act as a no-op. You must have some sort of command in the loop, even of only an echo
or continue
.
Use any tools or commands you wish.
#!/bin/sh
site='www.unix.com'
until $(ping -q -c1 ${site} > /dev/null 2>&1)
do
echo "${site} is unreachable. Retrying"
# continue
done
echo "online"
You can modify the until
clause to use almost any tool you want this way. I use ping because many commercial boxes do not have "netcat" or the like. Even if one does, it does not mean you have the access needed to run the command. Pinging the domain confirms I can actually resolve names on the Internet.
Everything is POSIX (except the tool that does the actual check, of course) so it does not require Bashisms and it is easy to modify to suit my needs.

- 109
- 1
- 4
This is a script who test internet connection: sometimes unique DNS server can give timeout for any reason so... let's use other servers by
ping=NOK ; debug= ; for (( ; ; )) do
value=9.9.9.9 ; if ping -q -w 2 -c 1 $value > /dev/null; then ping=OK ; debug=$value ; break ; fi
value=8.8.8.8 ; if ping -q -w 2 -c 1 $value > /dev/null; then ping=OK ; debug=$value ; break ; fi
value= ; break;
done
if [ "$ping" == "NOK" ]; then echo No internet !!! ; else echo Internet connection is $ping \(result given by $value DNS server\). ; fi
read $r

- 15
- 3