With this I can check, that there is "internet connection". if there is no "internet connection" (succesfull pings to this 2 places), then it waits 600 sec, then it runs along:

ping -W 1 -c 4 www.google.com >& /dev/null && ping -W 1 -c 4 www.yahoo.com >& /dev/null || sleep 600

But: how could I rewrite this one line, so that it loops until there is internet connection?

while ! ping -W 1 -c 4 www.google.com >& /dev/null ||
      ! ping -W 1 -c 4 www.yahoo.com >& /dev/null; do
  sleep 600

Though I'd just test connectivity to an IP address; is Google's public DNS server (it has very high availability). Testing whether DNS works is unreliable anyway because the entry may be in the cache.

while ! ping -W 1 -c 1 >&/dev/null; do sleep 600; done

Ping isn't always the best way to check internet connectivity. Many places (especially enterprise networks) block all but web access. You can test whether the web is working by downloading a file from a high-availability server. This tests DNS as well, at least from the HTTP proxy's point of view (which again is often what matters).

while ! wget -q -O /dev/null --no-cache http://www.google.com/; do sleep 6000; done
  • while ! ping -W 1 -c 4 www.yahoo.com; do sleep 60; done >& /dev/null – LanceBaynes Apr 3 '11 at 12:22
  • Need to change && to || to match the test from the OP. (A & B) == (~A | ~B). – Arcege Apr 3 '11 at 18:30

Some flaws with some of the above approaches, and why a comprehensive "is the internet working" can't really be done in one line:

  • You should always check if your link is active before even trying to ping anything. If there is no cable plugged into your Ethernet port or your stupid cat chewed the wire, nothing is going to work.

  • Should test localhost first. That will verify the integrity of your TCP/IP stack.

  • Relying on DNS resolution by specifying doman names can fail if your DNS server is unreachable or blocked. Just because your preferred DNS server is down doesn't mean you can't connect to other hosts via the Internet

  • Not good to always use the same address or host to check for connectivity, on a server you don't own. You should test a variety/well-randomized set of known-to-be-always-up hosts, preferably hosts you own that are outside of your network.

  • I'd even go so far to say that you should use a variety of protocols to really see if the "internet" is up or not. Perhaps a zombie machine on your network sent out a flood of pings as part of a DDoS and your ISP blocked ICMP.

If you really must have a one-line approach, what I would do is a traceroute to google.com or other well known Internet site of your choice. Just once. Find out how many hops your traffic takes to get out of your service provider's network. Subsequently, you can use a traceroute to test your external connectivity, but limit it to that many hops. If the final ping in the traceroute is successful, then you can get out of the network. Wish there was a "traceroute-like" utility for other protocols, such as HTTP and such.

  • 1
    You may be interested in tcptraceroute. For a simple test, if you know your Internet access provider isn't blocking pings, is as reliable as they get (it's Google's public DNS server, and they're very good at availability). If you want to test web connectivity, wget -q -O /dev/null --no-cache http://www.google.com/ is a good test. – Gilles Apr 4 '11 at 20:29
  • 1
    But if any of those things is broken, ping will fail. I think the point here is the simplest way of telling you if everything is working. If ping fails, then you can investigate the list of things you mention. – Mikel Apr 4 '11 at 21:25

You can just use a while loop from the shell.

while true; do
    if ping -W 1 -c 4 www.google.com >& /dev/null &&
       ping -W 1 -c 4 www.yahoo.com >& /dev/null; then
    sleep 600

The /bin/true and test 0 commands will always return 0 (true), but true may not always be a builtin.

  • That's way more complicated than it needs to be! – Gilles Apr 3 '11 at 12:08
  • 1
    That's readable. Pretty much all he's done is to wrap it in a while loop and reformat it; he didn't make it much more complicated at all. – Kevin M Apr 3 '11 at 12:22
  • @Gilles: I find yours more elegant, but Arcege's has simpler boolean logic (a && b) versus (!a || !b), which might be why some people prefer it. – Mikel Apr 4 '11 at 21:31
  • @Mikel: My complaint is against while true; do if ...; then break; fi (sorry if that wasn't clear earlier). That's not simple at all. !a||!b vs !(a&&b) is a trivial difference. – Gilles Apr 4 '11 at 21:35
  • @Gilles: Yes, that's the part I don't like too. But clearly at least Kevin M and one other person prefer this version. Maybe they can comment here and say why. – Mikel Apr 4 '11 at 21:38

To make the logic a little clearer, you could write the check in a subshell, e.g.

while ! ( ping -W 1 -c 4 www.google.com >& /dev/null &&
          ping -W 1 -c 4 www.yahoo.com >& /dev/null ); do
    sleep 600

Or write the test in a function.

can_ping_internet() {
    ping -W 1 -c 4 www.google.com && ping -W 1 -c 4 www.yahoo.com

while ! can_ping_internet; do
    sleep 600
  • The second version is not a "one liner", but it's still shorter than at least one solution here. :-) – Mikel Apr 4 '11 at 21:44

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.