9

I have some anacron jobs which run daily. The scripts update local bzr and git repositories. Naturally these scripts need working network connections. I'm on a laptop and often wired and wireless internet do not come up fast enough. This causes my cron job to time out when pulling the repositories =(

So:

How to make sure the internet is up before running specific cron jobs? Or how to fail a job if there is no network, such that it is retried by anacron later again?

2
  • What language? Bash, Python, Perl? Aug 30, 2010 at 1:32
  • @Marco Ceppi: Any will do. But I don't know Perl =)
    – Dima
    Aug 30, 2010 at 22:31

9 Answers 9

9

I made a cron that did a ping test on a DNS server to ensure networking. Something like this:

ping 8.8.8.8 -c 1 -i .2 -t 60 > /dev/null 2>&1
ONLINE=$?

if [ ONLINE -eq 0 ]; then
    #We're offline
else
    #We're online
fi

Recently I've used something like this:

#!/bin/bash

function check_online
{
    netcat -z -w 5 8.8.8.8 53 && echo 1 || echo 0
}

# Initial check to see if we are online
IS_ONLINE=check_online
# How many times we should check if we're online - this prevents infinite looping
MAX_CHECKS=5
# Initial starting value for checks
CHECKS=0

# Loop while we're not online.
while [ $IS_ONLINE -eq 0 ]; do
    # We're offline. Sleep for a bit, then check again

    sleep 10;
    IS_ONLINE=check_online

    CHECKS=$[ $CHECKS + 1 ]
    if [ $CHECKS -gt $MAX_CHECKS ]; then
        break
    fi
done

if [ $IS_ONLINE -eq 0 ]; then
    # We never were able to get online. Kill script.
    exit 1
fi

# Now we enter our normal code here. The above was just for online checking

This isn't the MOST elegant - I'm not sure how else to check via a simple command or file on the system, but this has worked for me when needed.

2
  • I had to encapsulate the check_online calls in $(), so IS_ONLINE=$(check_online) Jan 22, 2022 at 16:41
  • I also suggest exitting with 0 at the end, this way one can reuse this script to call another one(s) like "./this_script.sh && ./cronJob.sh" Jan 22, 2022 at 16:42
8

I think you can use Upstart to help you there. Mind you, I haven't tested that code below works but something very similar should.

# /etc/init/update-repositories.conf - Update local repos
#

description     "Update local repos"

# this will run the script section every time network is up
start on (net-device-up IFACE!=lo)

task

script
    svn up && git fetch
#   do some other useful stuff
end script

That pretty much it. You might want to add some code to check that it does not run very often. You might also want to add start update-repositories to your crontab, it'll make sure your update will happen if you are on the net constantly for a prolonged period of time.

2
  • This code will run every time a network interface comes up, including every time your wireless drops and reconnects. If you only want it to run once a day, add logic to place/check a timestamp.
    – user535733
    Jan 18, 2014 at 3:46
  • Any idea whether this still works under systemd?
    – Kevin
    Jul 10, 2015 at 20:50
2

You can talk to NetworkManager to see whether you are connected or not:

$state = $(dbus-send --system --print-reply \
    --dest=org.freedesktop.NetworkManager \
    /org/freedesktop/NetworkManager \
    org.freedesktop.NetworkManager.state 2>/dev/null \
| awk '/uint32/{print $2}')
if [ $state = 3 ]; then
    echo "Connected!"
else
    echo "Not connected!"
fi
1
  • Nice. And ugly :) Seems like a good candidate for implementation in some standard tool for convenient shell access, or via a Python API, so it was more readable and didn't use magic values like "3".
    – nealmcb
    May 18, 2011 at 20:10
2

Just to wrap up a couple of the options here into a single script:

#! /bin/bash
# This script checks that the interface is up, and that an internet connection is available
# It is based on code from http://askubuntu.com/questions/3299/how-to-run-cron-job-when-network-is-up
#
# Then it sleeps for a random number of seconds between 30 and 600.
# This is based on code from http://tldp.org/LDP/abs/html/randomvar.html
#
# Collated by @JonTheNiceGuy on 2015-10-15

function check_ipaddr
{
  # Here we look for an IP(v4|v6) address when doing ip addr
  # Note we're filtering out 127.0.0.1 and ::1/128 which are the "localhost" ip addresses
  # I'm also removing fe80: which is the "link local" prefix

  ip addr | \
  grep -v 127.0.0.1 | \
  grep -v '::1/128' | \
  grep -v 'inet6 fe80:' | \
  grep -E "inet [[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+|inet6" | \
  wc -l
}

function check_google
{
  netcat -z -w 5 8.8.8.8 53 && echo 1 || echo 0
}

until [ `check_ipaddr` -gt 1 ]; do
  sleep 2
done

until [ `check_google` -eq 1 ]; do
  sleep 2
done

sleep $((RANDOM%570+30))

I plan to maintain this script at https://gist.github.com/JonTheNiceGuy/5cf4a23c8f2f755a9ca4

1

To expand on nixternal, the fping binary is excellent for that. You can cook it up in one-liners as in

$ fping -q yoo.mama && echo yes
$ fping -q www.google.com && echo yes
yes
$ 

As you see, yoo.mama does not like me but Google does. In crontab, you'd do something like

5 5 * * *  root   fping -q google.com && /some/script/I/want --to --run
1
  • 3
    That won't run the command later if the network is down. How could that be accomplished?
    – aperson
    Aug 30, 2010 at 5:00
0

What I do is create a shell script that does what you need, ie. checks for network connection and then fires off the updates. Then call the script from cron.

0
until ifconfig eth | grep -qE 'addr:([[:digit:]]+\.?)+'; do
   sleep 2
done
1
  • This answer doesn't quite explain what the user should be doing to resolve their issue.
    – TomKat
    Jan 9, 2014 at 9:15
0

I've defined a bash alias to answer this question:

alias netstate='ip link show | egrep -q '\''UP,LOWER_UP.* state UP'\'' && echo UP || echo DOWN'

You could use it, or process the output of ip link show yourself.

To handle "net goes down/net comes up" see my net-o-matic script at net-o-matic

0

I found ping solutions gave me network errors which spammed my logs unless I laboriously directed errors to /dev/null

Network Manager can be used:

if nmcli general | grep "^connected" >/dev/null
then
   echo "nmcli connected"
fi

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .