12

It seems that my Raspberry Pi server loses wifi connection after a random time and is somehow not able to recover automatically.

Usually a reboot done by hand resolves the problem.

I would like to make it reboot automatically if there is no wifi after about 30 minutes. How can I do that?

  • 5
    Have you tried taking the interface down and bringing it back up? How about unloading and re-loading the kernel module for your wireless card? There might be something else you can do to reset the card without rebooting. – hololeap Jul 7 '14 at 9:25
  • 1
    yeah this would probably also work, but the main issue here is how to detect this automatically and then perform the appropriate action. – clamp Jul 7 '14 at 10:32
9

This is essentially Warwick's answer, just with step-by-step instructions.


  1. Create the following shell script in your home folder:

    check_inet.sh

    #!/bin/bash
    
    TMP_FILE=/tmp/inet_up
    
    # Edit this function if you want to do something besides reboot
    no_inet_action() {
        shutdown -r +1 'No internet.'
    }
    
    if ping -c5 google.com; then
        echo 1 > $TMP_FILE
    else
        [[ `cat $TMP_FILE` == 0 ]] && no_inet_action || echo 0 > $TMP_FILE
    fi
    
  2. Change the permissions so it is executable

    $ chmod +x check_inet.sh
    
  3. Edit /etc/crontab using sudo and add the following line (replace yourname with your actual username):

    */30 * * * * /home/yourname/check_inet.sh
    
4

One way would be to put an entry in root's cron that runs a script every 30 minutes. The script would test the WIFI connection, perhaps using ping, and write the result to a file in /tmp - 1 for connection exists, 0 if it doesn't. Subsequent iterations of the script would then check that file, and if it was 0, and the WIFI connection was still bad, run an init 6 command.

3

I think hololeap solution is working.

My solution checks every N minutes (depending on how you configure your crontab) for a working network connection. If the check fails I keep track of the failure. When failure count is > 5 I try to restart wifi (you can also reboot Raspberry if wifi restart fails, check the comments).

Here's a GitHub repo always containing the latest version of the script: https://github.com/ltpitt/bash-network-repair-automation

Here's, according to stackexchange general policy (all answers should not just contain links), also the file network_check.sh, copy and paste it into any folder you like, installing instructions are in script's comments.

#!/bin/bash
# Author:
# twitter.com/pitto
#
# HOW TO INSTALL:
#
# 1) Install ifupdown and fping with the following command:
# sudo apt-get install ifupdown fping
#
# 2) Then install this script into a folder and add to your crontab -e this row:
# */5 * * * * /yourhome/yourname/network_check.sh
#
# Note:
# If you want to perform automatic repair fsck at reboot
# remember to uncomment fsck autorepair here: nano /etc/default/rcS

# Let's clear the screen
clear

# Write here the gateway you want to check to declare network working or not
gateway_ip='www.google.com'

# Here we initialize the check counter to zero
network_check_tries=0

# Here we specify the maximum number of failed checks
network_check_threshold=5

# This function will be called when network_check_tries is equal or greather than network_check_threshold
function restart_wlan0 {
    # If network test failed more than $network_check_threshold
    echo "Network was not working for the previous $network_check_tries checks."
    # We restart wlan0
    echo "Restarting wlan0"
    /sbin/ifdown 'wlan0'
    sleep 5
    /sbin/ifup --force 'wlan0'
    sleep 60
    # If network is still down after recovery and you want to force a reboot simply uncomment following 4 rows
    #host_status=$(fping $gateway_ip)
    #if [[ $host_status != *"alive"* ]]; then
    #    reboot
    #fi
}

# This loop will run network_check_tries times and if we have network_check_threshold failures
# we declare network as not working and we restart wlan0
while [ $network_check_tries -lt $network_check_threshold ]; do
    # We check if ping to gateway is working and perform the ok / ko actions
    host_status=$(fping $gateway_ip)
    # Increase network_check_tries by 1 unit
    network_check_tries=$[$network_check_tries+1]
    # If network is working
    if [[ $host_status == *"alive"* ]]; then
        # We print positive feedback and quit
        echo "Network is working correctly" && exit 0
    else
        # If network is down print negative feedback and continue
        echo "Network is down, failed check number $network_check_tries of $network_check_threshold"
    fi
    # If we hit the threshold we restart wlan0
    if [ $network_check_tries -ge $network_check_threshold ]; then
        restart_wlan0
    fi
    # Let's wait a bit between every check
    sleep 5 # Increase this value if you prefer longer time delta between checks
done

edit 1/26/2018: I've removed the temp files in order to let the script run in memory and avoid writing on Raspberry's SD card.

  • 1
    This script avoids restart on temporary disconnects. Excellent, thanks! – wezzix Jul 5 '17 at 17:06
  • 1
    You seem to have made a major change in this script.  As I understood it, the previous version would make one pass, doing stuff (including updating tmp files), and exit.  It didn’t contain any loops; rather, it depended on cron to run it every five minutes.  If the network was down for five consecutive checks (i.e., for a span of about half an hour), the script would do things to try to reset the network.  This seemed to be a good answer to the question, although the fact that it wrote to tmp files was a bit of a drawback.  … (Cont’d) – Scott Jan 28 '18 at 18:43
  • (Cont’d) …  The new version contains a loop, and checks the network every five seconds. If the network is down for five consecutive checks (i.e., for a span of about half a minute), the script does things to try to reset the network. (This seems to be different from what the question asks for.) And here it gets a little weird. After it detects a five-consecutive-times network failure and resets the network, the script exits. (And, incidentally, it exits without ever checking whether the network actually came back up.) … (Cont’d) – Scott Jan 28 '18 at 18:43
  • (Cont’d) …  But, as long as the network is up, the script keeps running forever, waiting for the network to fail. Meanwhile, cron keeps restarting the script every five minutes. If the network stays up for an hour, there will be a dozen copies of the script running. And, if the network fails then, those dozen processes will do battle with each other, asynchronously doing ifdown and ifup, maybe fixing the network, and maybe not. … … … … … … … … … … … … … … … … … … … … … … … … … … … … … If I’ve misunderstood something, please explain it to me. … (Cont’d) – Scott Jan 28 '18 at 18:43
  • (Cont’d) …  (1) If you’re going to make such a major redesign of an answer that’s been posted for over a year, you should say what you have done. “I’ve removed the temp files in order to let the script run in memory” is not an adequate description of your changes. (2) It seems like you have a collection of square pegs, round pegs, square holes, and round holes, and you haven’t gotten them matched up right. You should either modify the script to exit when it sees that the network is up, or modify it to run forever, and change the crontab to start the script only once (i.e., at boot time). – Scott Jan 28 '18 at 18:46
0

I modiffied Pitto's script for my multitech mtac loraWAN gateway (no fping). I also added a log file.

#!/bin/bash
# Author: 
# twitter.com/pitto
#
# HOW TO INSTALL:
#
# 1) Install ifupdown with the following command:
# sudo apt-get install ifupdown
#
# 2) Create files in any folder you like (ensure that the filename variables, set below,
# match the names of the files you created) with the following commands:
# sudo touch /home/root/scripts/network_check_tries.txt &&
#                               sudo chmod 777 /home/root/network_check_tries.txt
# sudo touch /home/root/scripts/N_reboots_file.txt      &&
#                               sudo chmod 777 /home/root/N_reboots_file.txt
# sudo touch /home/root/scripts/network_check.log       &&
#                               sudo chmod 777 /home/root/network_check.log
#
# 3) Then install this script into a folder and add to your crontab -e this row:
# */5 * * * * /yourhome/yourname/network_check.sh
#
# Note:
# If additionally you want to perform automatic repair fsck at reboot
# remember to uncomment fsck autorepair here: nano /etc/default/rcS

# Specify the paths of the text file where the network failures count, reboot count,
# and log will be held:
network_check_tries_file='/home/root/network_check_tries.txt'
N_reboots_file='/home/root/N_reboots_file.txt'
log_file='/home/root/network_check.log'

# Save file contents into corresponding variables:
network_check_tries=$(cat "$network_check_tries_file")
N_reboots=$(cat "$N_reboots_file")


# If host is / is not alive we perform the ok / ko actions that simply involve
# increasing or resetting the failure counter
ping -c1 google.com
if [ $? -eq 0 ]
then
    # if you want to log when there is no problem also,
    # uncomment the following line, starting at "date".
    echo 0 > "$network_check_tries_file" #&& date >> "$log_file" && echo -e "-- Network is working correctly -- \n" >> "$log_file"
else
    date >> "$log_file" && echo -e "-- Network is down... -- \n" >> "$log_file" && echo "$(($network_check_tries + 1))" > "$network_check_tries_file"
fi

# If network test failed more than 5 times (you can change this value to whatever you
# prefer)
if [ "$network_check_tries" -gt 5 ] 
then
    # Time to restart ppp0
    date >> "$log_file" && echo "Network was not working for the previous $network_check_tries checks." >> "$log_file" && echo "Restarting ppp0" >> "$log_file"
    killall pppd
    sleep 20
    /usr/sbin/pppd call gsm
    sleep 120
    # Then we check again if restarting wlan0 fixed the issue;
    # if not we reboot as last resort
    ping -c1 google.com
    if [ $? -eq 0 ]
    then
        date >> "$log_file" && echo -e "-- Network is working correctly -- \n" >> "$log_file" && echo 0 > "$network_check_tries_file"
    else
        date >> "$log_file" && echo -e  "-- Network still down after ifdownup... reboot time!-- \n" >> "$log_file" && echo 0 > "$network_check_tries_file" && echo "$(($N_reboots + 1))" > "$N_reboots_file" && reboot
    fi
fi
  • (1) Why do you still talk about ifupdown if you don't use it/them? (2) Why did you change gateway_ip from a variable to a hard-coded constant? – Scott Jan 19 '18 at 20:07
  • hi scott, I forgot to delette the ifup ifdown comments. I forgot to change the hardcoded gatewy_ip. – user3036425 Jan 20 '18 at 23:47
  • Nice! I've added a new version that is not using temp files (writing on Raspberry's SD was not such a great idea), you can check it in my answer. – Pitto Jan 26 '18 at 14:59
  • This script inherits a couple of issues that were in the original version of Pitto’s script (which have subsequently been corrected): (1) If the network is down starting at 00:00:01 (one second after midnight), the script will not react until 00:35 (i.e., 35 minutes later, on the seventh check), because, even though it increments the value in the network_check_tries_file file (when ping fails), it doesn’t increment the network_check_tries variable.  … (Cont’d) – Scott Feb 14 '18 at 20:17
  • (Cont’d) …  So the script runs seven times (at 00:05, 00:10, 00:15, 00:20, 00:25, 00:30, and 00:35) with network_check_tries equal to 0, 1, 2, 3, 4, 5, and 6 — and it’s only on the seventh invocation (with network_check_tries equal to 6) that the if [ "$network_check_tries" -gt 5 ] test succeeds.  Arguably, this is the correct behavior.  As far as the script knows, the network may have gone down at 00:04:59, so it takes seven consecutive failures to be sure you have covered a 30 minute period.  … (Cont’d) – Scott Feb 14 '18 at 20:17

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.