How to test an Internet connection with bash?

后端 未结 19 1423
青春惊慌失措
青春惊慌失措 2020-11-27 09:26

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

19条回答
  •  孤城傲影
    2020-11-27 10:21

    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:

    1. It's possible for your computer to be connected to a network without that network having internet access
    2. It's possible for a server to be down without the entire internet being inaccessible
    3. 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:

    1. It is robust against all the false positives and negatives I outlined above
    2. The requests all happen in parallel to maximize speed
    3. 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

提交回复
热议问题