7

Good day! Is there any way to include a timer (timestamp?or whatever term it is) in a script using bash? Like for instance; every 60 seconds, a specific function checks if the internet is down, if it is, then it connects to the wifi device instead and vice versa. In short, the program checks the internet connection from time to time.

Any suggestions/answers will be much appreciated. =)

Suezy
  • 1,071
  • 4
  • 13
  • 19

6 Answers6

18

Blunt version

while sleep 60; do
  if ! check_internet; then
    if is_wifi; then
       set_wired
    else
       set_wifi
    fi
  fi
done

Using the sleep itself as loop condition allows you to break out of the loop by killing the sleep (i.e. if it's a foreground process, ctrl-c will do).

If we're talking minutes or hours intervals, cron will probably do a better job, as Montecristo pointed out.

falstro
  • 34,597
  • 9
  • 72
  • 86
5

You may want to do a man cron.

Or if you just have to stick to bash just put the function call inside a loop and sleep 60 inside the iteration.

Alberto Zaccagni
  • 30,779
  • 11
  • 72
  • 106
4

Please find here a script that you can use, first add an entry to your cron job like this:

$ sudo crontab -e * * * * * /path/to/your/switcher

This is simple method that reside on pinging an alive server continuously every minute, if the server is not reachable, it will switch to the second router defined bellow.

surely there are better way, to exploit this issue.

$ cat > switcher

#!/bin/sh

route=`which route`
ip=`which ip`

# define your email here
mail="user@domain.tld"

# We define our pingable target like 'yahoo' or whatever, note that the host have to be 
# reachable every time
target="www.yahoo.com"

# log file
file="/var/log/updown.log"

# your routers here
router1="192.168.0.1"
router2="192.168.0.254"

# default router
default=$($ip route | awk '/default/ { print $3 }')

# ping command
ping -c 2 ${target}

if [ $? -eq 0 ]; then
   echo "`date +%Y%m%d-%H:%M:%S`: up" >> ${file}

else
   echo "`date +%Y%m%d-%H:%M:%S`: down" >> ${file}

   if [ ${default}==${router1} ]; then
       ${route} del default gw ${router1}
       ${route} add default gw ${router2}
   elif [ ${default}==${router2} ];  then
       ${route} del default gw ${router2}
       ${route} add default gw ${router1}
   fi
   # sending a notification by mail or may be by sms
   echo "Connection problem" |mail -s "Changing Routing table" ${mail}
fi
Ali Mezgani
  • 1,229
  • 3
  • 13
  • 19
3

I liked William's answer, because it does not need polling. So I implemented the following script based on his idea. It works around the problem that control has to return to the shell.

#!/bin/sh

someproc()
{
        sleep $1
        return $2
}

run_or_timeout()
{
        timeout=$1
        shift

        {
                trap 'exit 0' 15
                "$@"
        } &
        proc=$!

        trap "kill $proc" ALRM
        {
                trap 'exit 0' 15
                sleep $timeout
                kill -ALRM $$
        } &
        alarm=$!

        wait $proc
        ret=$?

        # cleanup
        kill $alarm
        trap - ALRM
        return $ret
}

run_or_timeout 0 someproc 1 0
echo "exit: $? (expected: 142)"
run_or_timeout 1 someproc 0 0
echo "exit: $? (expected: 0)"
run_or_timeout 1 someproc 0 1
echo "exit: $? (expected: 1)"
drizzd
  • 3,074
  • 1
  • 17
  • 13
1

You can do something like the following, but it is not reliable:

#!/bin/sh

trap handle_timer USR1

set_timer() { (sleep 2; kill -USR1 $$)& }
handle_timer() {
    printf "%s:%s\n" "timer expired" "$(date)";
    set_timer
}

set_timer
while true; do sleep 1; date; done

One problem with this technique is that the trap will not take effect until the current task returns to the shell (eg, replace the sleep 1 with sleep 10). If the shell is in control most of the time (eg if all the commands it calls will terminate quickly), this can work. One option of course, is to run everything in the background.

William Pursell
  • 204,365
  • 48
  • 270
  • 300
0

Create a bash script that checks once if internet connection is down and add the script in a crontab task that runs every 60 seconds.

David Aleu
  • 3,922
  • 3
  • 27
  • 48