What's new
  • SNBForums Code of Conduct

    SNBForums is a community for everyone, no matter what their level of experience.

    Please be tolerant and patient of others, especially newcomers. We are all here to share and learn!

    The rules are simple: Be patient, be nice, be helpful or be gone!

Tutorial Automatically Reboot Asus Router on Network Failures

bg604

Occasional Visitor
I wrote a script to automatically detect internet outages and reboot the router if needed, ensuring minimal downtime.

It monitors internet connectivity by pinging multiple well-known IP addresses (Google DNS, Cloudflare, and Quad9) up to three times each. If any of the pings succeed, the script exits.

If all attempts fail, the script triggers a reboot of the router, which helps address common connectivity issues. This approach ensures the router's settings are refreshed and can help resolve certain network problems without manual intervention.

Please let me know what you think, first time doing something like this.

Step 1: Enable Persistent JFFS2 partition and SSH
  1. Log into Asus router – 192.168.xxx.xxx and log in using your credentials.
  2. Navigate to Administration -> System tab.
  3. In Persistent JFFS2 partition section:
    • Enable JFFS custom scripts and configs – Yes.
  4. In Service section:
    • Enable SSH - LAN only.
    • Allow SSH Port Forwarding - No.
    • Set SSH Port - 22.
    • Enable Allow Password Login - Yes.
    • Leave Authorized Keys blank.
    • Set Idle Timeout - 20.

Step 2: Install an SSH client on Windows
  1. Download and install PuTTY (https://www.putty.org/)

Step 3: Connect to your router via SSH using PuTTY
  1. Open PuTTY.
  2. Enter Host Name: 192.168.xxx.xxx.
  3. Set Port: 22
  4. Select Connection: SSH
  5. Click Open and confirm the security alert.
  6. Log in using your Asus router credentials.

Step 4: Create the script file

Open PuTTY and run the following command:
Bash:
vi /jffs/scripts/ping_reboot.sh


Step 5: Enter Insert Mode

Press i to enter insert mode in the editor


Step 6: Copy and paste the script

Bash:
#!/bin/sh
# Script to monitor internet connectivity and reboot the router if all ping attempts fail.
# Log file and self-check mechanism ensure efficient and safe operation.

# Log file location (persistent across reboots)
LOG_FILE="/jffs/ping_reboot.log"

# Maximum log size in bytes (e.g., 512KB = 524288 bytes)
MAX_LOG_SIZE=524288

# Number of ping attempts per target
ATTEMPTS=3

# List of ping targets (space-separated IPs)
PING_TARGETS="8.8.8.8 1.1.1.1 9.9.9.9"

# Minimum time between reboots (in seconds, e.g., 30 minutes = 1800 seconds)
MIN_REBOOT_INTERVAL=1800

# File to store the timestamp of the last reboot
LAST_REBOOT_FILE="/jffs/last_reboot_time"

# Get the current time in seconds since the epoch
CURRENT_TIME=$(date +%s)

# Rotate the log file if it exceeds the maximum size
rotate_log() {
    if [ -f "$LOG_FILE" ]; then
        LOG_SIZE=$(stat -c %s "$LOG_FILE")  # Get the size of the log file
        if [ "$LOG_SIZE" -ge "$MAX_LOG_SIZE" ]; then
            echo "Log file size exceeds limit. Rotating log..." > "$LOG_FILE"
        fi
    fi
}

# Self-check to prevent repeated reboots within the specified interval
if [ -f "$LAST_REBOOT_FILE" ]; then
    LAST_REBOOT=$(cat "$LAST_REBOOT_FILE")  # Read the last reboot timestamp
    if [ $((CURRENT_TIME - LAST_REBOOT)) -lt "$MIN_REBOOT_INTERVAL" ]; then
        echo "Last reboot was less than $((MIN_REBOOT_INTERVAL / 60)) minutes ago. Exiting script." >> "$LOG_FILE"
        logger -t "$(basename $0)" "Last reboot was less than $((MIN_REBOOT_INTERVAL / 60)) minutes ago. Exiting script."
        exit 0
    fi
fi

# Log tag for identifying messages in the ASUS GUI system log
TAG="$(basename $0)"

# Start the ping test
echo "Starting the ping test at $(date)"
logger -t "$TAG" "Starting the ping test at $(date)"

# Loop through the list of ping targets
for PING_TARGET in $PING_TARGETS; do
    echo "Pinging target: $PING_TARGET"
    logger -t "$TAG" "Pinging target: $PING_TARGET"

    COUNTER=0
    while [ "$COUNTER" -lt "$ATTEMPTS" ]; do
        echo "Attempt $((COUNTER + 1)) to ping $PING_TARGET..."
        logger -t "$TAG" "Attempt $((COUNTER + 1)) to ping $PING_TARGET..."

        # Ping the target
        ping -c 4 "$PING_TARGET" > /dev/null 2>&1
        if [ "$?" -eq 0 ]; then  # If ping succeeds
            echo "Ping to $PING_TARGET succeeded."
            logger -t "$TAG" "Ping to $PING_TARGET succeeded."
            exit 0
        fi

        # Log failed attempt and increment the counter
        COUNTER=$((COUNTER + 1))
        rotate_log  # Check if the log file needs rotation
        echo "Ping to $PING_TARGET failed (attempt $COUNTER) at $(date)" >> "$LOG_FILE"
        logger -t "$TAG" "Ping to $PING_TARGET failed (attempt $COUNTER) at $(date)"
    
        # Wait before the next attempt
        echo "Waiting 5 seconds before the next attempt..."
        sleep 5
    done
done

# If all pings fail, log the failure and reboot the router
rotate_log  # Check if the log file needs rotation
echo "All pings failed. Rebooting router at $(date)" >> "$LOG_FILE"
logger -t "$TAG" "All pings failed. Rebooting router at $(date)"
echo "Rebooting router due to failed ping attempts..." >> "$LOG_FILE"
logger -t "$TAG" "Rebooting router due to failed ping attempts..."

# Record the current time as the last reboot timestamp
echo "$CURRENT_TIME" > "$LAST_REBOOT_FILE"

# Allow time for the log to be written before reboot
sleep 10
service reboot


Step 7: Save and exit
  1. After pasting the script, press Esc
  2. Type :wq and hit Enter to save and exit.

Step 8: Permit the script file to be executable
  1. Run the following command:
Bash:
chmod +x /jffs/scripts/ping_reboot.sh

Step 9: Add the Persistent Cron Job​

  1. Open the services-start file for editing:
    Bash:
    vi /jffs/scripts/services-start
  2. Enter insert mode by pressing i and add the following lines:
    Bash:
    #!/bin/sh
    cru a PingReboot "*/5 * * * * /jffs/scripts/ping_reboot.sh"
  3. Save and exit the file by pressing Esc, typing :wq, and pressing Enter.
  4. Make the services-start script executable:
    Bash:
    chmod +x /jffs/scripts/services-start

Step 10: Test the script as-is (run manually)

Bash:
cd /jffs/scripts

Bash:
./ping_reboot.sh

Output should be:
Starting the ping test at DATE
Pinging target: 8.8.8.8
Attempt 1 to ping 8.8.8.8...
Ping to 8.8.8.8 succeeded.

Step 11: Reboot router and verify the Cron Job

1. Reboot router
2. After rebooting the router, check if the cron job is active by running:
Bash:
cru l
You should see:
PingReboot = */5 * * * * /jffs/scripts/ping_reboot.sh #PingReboot#


Step 12: View the log

1. Navigate to the /jffs directory:
Bash:
cd /jffs

2. View the entire log file:
Bash:
cat ping_reboot.log

3. Clear the log (Optional)
Bash:
> ping_reboot.log


Step 13: Self-Test

After completing the setup, unplug the WAN connection to simulate an internet outage and observe whether the script triggers a reboot correctly.
 
Last edited:
If all attempts fail, it triggers a reboot, which can resolve many common network issues like temporary ISP outages and helps ensure your router stays connected to the internet without requiring manual intervention.

The common advice for ISP outages is to reboot the modem, not the router.
 
Please let me know what you think, first time doing something like this.
Well done on your script.

I think you forgot to include the last line where it presumably executes a service reboot command.

May I also suggest that you post your script inside a CODE block instead of QUOTE block as it makes it more readable and doesn't mess up the formatting so much.
 
Well done on your script.

I think you forgot to include the last line where it presumably executes a service reboot command.

May I also suggest that you post your script inside a CODE block instead of QUOTE block as it makes it more readable and doesn't mess up the formatting so much.

Thanks - I updated to a CODE block and added reboot
 
and it works! once the router rebooted it reconnected to my ISP modem and WiFi/Internet was up again

here is the log details

Bash:
bg604@GT-AX11000:/tmp/home/root# cat /jffs/ping_reboot.log

Ping to 8.8.8.8 failed (attempt 1) at Tue Jan  7 18:50:13 PST 2025
Ping to 8.8.8.8 failed (attempt 2) at Tue Jan  7 18:50:46 PST 2025
Ping to 8.8.8.8 failed (attempt 3) at Tue Jan  7 18:51:19 PST 2025
Ping to 1.1.1.1 failed (attempt 1) at Tue Jan  7 18:51:52 PST 2025
Ping to 1.1.1.1 failed (attempt 2) at Tue Jan  7 18:52:25 PST 2025
Ping to 1.1.1.1 failed (attempt 3) at Tue Jan  7 18:52:58 PST 2025
Ping to 9.9.9.9 failed (attempt 1) at Tue Jan  7 18:53:31 PST 2025
Ping to 9.9.9.9 failed (attempt 2) at Tue Jan  7 18:54:04 PST 2025
Ping to 9.9.9.9 failed (attempt 3) at Tue Jan  7 18:54:37 PST 2025
All pings failed. Rebooting router at Tue Jan  7 18:54:57 PST 2025
Rebooting router due to failed ping attempts...
 
Last edited:
@bg604,

You dear sir, are a gentleperson and a scholar. Thank you so much for this script, it's going to help me create a few cron jobs which I've been wanting to create for a while.

Thanks again :)

Noob
 
Actually,

Is there a way to post the echos to the main ASUS GUI system log as well? Or would that happen anyway?

Noob
 
Step 6: Copy and paste the script
The first line of your script should be:
Code:
#!/bin/sh

A more appropriate command to reboot in Asuswrt would be:
Code:
service reboot

Step 9: Create the Cron Job to Run the Script Automatically

1. Open the cron jobs with:
Bash:
crontab -e
2. Add the following line:
Bash:
*/5 * * * * /jffs/scripts/ping_reboot.sh #PingReboot#
Editing the crontab directly in Asuswrt means that change would be lost after a reboot. To make a persistent crontab entry in Asuswrt-Merlin place a cru command in /jffs/scripts/services-start as follows:
Code:
#!/bin/sh

cru a PingReboot "*/5 * * * * /jffs/scripts/ping_reboot.sh"
 
Last edited:
Okay thanks... I've made those changes. I was wondering why it would disappear in crontab -e after a reboot. Thanks!


The first line of your script should be:
Code:
#!/bin/sh

A more appropriate command to reboot in Asuswrt would be:
Code:
service reboot


Editing the crontab directly in Asuswrt means that change would be lost after a reboot. To make a persistent crontab entry in Asuswrt-Merlin place a cru command in /jffs/scripts/services-start as follows:
Code:
#!/bin/sh

cru a PingReboot "*/5 * * * * /jffs/scripts/ping_reboot.sh"
 
Actually,

Is there a way to post the echos to the main ASUS GUI system log as well? Or would that happen anyway?

Noob

I've updated the script write to the system log in the Asus GUI using logger
Jan 8 09:55:00 bg604: Starting the ping test at Wed Jan 8 09:55:00 PST 2025
Jan 8 09:55:00 bg604: Pinging target: 8.8.8.8
Jan 8 09:55:00 bg604: Attempt 1 to ping 8.8.8.8...
Jan 8 09:55:03 bg604: Ping to 8.8.8.8 succeeded.
 
I've updated the script write to the system log in the Asus GUI using logger
Tip: if you use loggerwith -t you could specify the tag, I.e using $0 to have it using your script filename.

Example from my Wireguard Watchdog script:
Code:
logger -t $(basename $0) "Interface $IF not found or not enabled - exiting"

Resulting syslog:
Code:
Jan  8 20:57:31 wgc-watchdog: Interface wgc3 not found or not enabled - exiting
 
Last edited:
Tip: if you use loggerwith -t you could specify the tag, I.e using $0 to have it using your script filename.

Example from my Wireguard Watchdog script:
Code:
logger -t $(basename $0) "Interface $IF not found or not enabled - exiting"

Resulting syslog:
Code:
Jan  8 20:57:31 wgc-watchdog: Interface wgc3 not found or not enabled - exiting

okay good...

i've setup a TAG variable with logger


Before:
Jan 8 12:05:00 bg604: Starting the ping test at Wed Jan 8 12:05:00 PST 2025
Jan 8 12:05:00 bg604: Pinging target: 8.8.8.8
Jan 8 12:05:00 bg604: Attempt 1 to ping 8.8.8.8...
Jan 8 12:05:03 bg604: Ping to 8.8.8.8 succeeded.

After:
Jan 8 12:10:39 ping_reboot.sh: Starting the ping test at Wed Jan 8 12:10:39 PST 2025
Jan 8 12:10:39 ping_reboot.sh: Pinging target: 8.8.8.8
Jan 8 12:10:39 ping_reboot.sh: Attempt 1 to ping 8.8.8.8...
Jan 8 12:10:42 ping_reboot.sh: Ping to 8.8.8.8 succeeded.
 
Last edited:
Another user bitten by the scripting bug... careful you'll go from 50 line simple scripts to 1000+ lines in no time ;)

wicens internet check
 
Another user bitten by the scripting bug... careful you'll go from 50 line simple scripts to 1000+ lines in no time ;)

wicens internet check
@Maverickcdn, funny, I was thinking of your Addon when I saw this post, but I wasn’t sure if it could also force a reboot when the WAN IP changed or whether it just sends a notification. I know it sends a notification when the router reboots in an unscheduled way e.g. power goes off, which is what I used it for.
 
@Maverickcdn, funny, I was thinking of your Addon when I saw this post, but I wasn’t sure if it could also force a reboot when the WAN IP changed or whether it just sends a notification. I know it sends a notification when the router reboots in an unscheduled way e.g. power goes off, which is what I used it for.
The OP script is based around if the Internet connection is down and rebooting the router, mine is only a WAN IP monitor and my entire script relies on the Internet connection being up.

To your point though mine could force a reboot if the IP changed (custom WAN IP change script / option 5)
 
To your point though mine could force a reboot if the IP changed (custom WAN IP change script / option 5)
Yeah I guess I was sort of suggesting that in an oblique way, given you already have the base script so it’d be a little addition to it that would improve it yet again :-)!

Feel kinda bad for the OP suggesting this though, as they’ve already done a great job with their script; it’s just that yours is already installed and setup so it’s just a modification…
 
Hi guys,

Iv attempted to hijack this script to switch my wireguard server on if my phone IP is not detected on my LAN. Iv hit a wall with it and i am hoping someone can help me fix what i have 😅

Code:
#!/bin/sh

# Script must be bound to the Wireguard server Interface
IF=wgs$1

# Number of ping attempts per target
ATTEMPTS=5

# Log tag for identifying messages in the ASUS GUI system log
TAG="$(basename $0)"

# Start the ping test
logger -t "$TAG" "Checking for Android phone..."

COUNTER=0

    while [ "$COUNTER" -lt "$ATTEMPTS" ]; do
        logger -t "$TAG" "Android ping attempt $((COUNTER + 1))"

# Ping the target
        ping -c 1 -w 1 192.168.50.241 > /dev/null 2>&1

# If ping succeeds       
        if [ "$?" -eq 0 ]; then
        ENABLED=$(nvram get "$IF"_enable)
            if [ -z "$1" ] || [ -z "$ENABLED" ] || [ "$ENABLED" -ne "1" ] ; then
            logger -t "$TAG" "Android device detected."
            logger -t "$TAG" "Wireguard Server already deactivated."
            exit 0

                else
                if [ -z "$1" ] ; then
                logger -t "$TAG" "Android device detected."
                logger -t "$TAG" "Deactivating WG Server..."
                nvram set wgs1_enable=0
                service restart_wgs
                service restart_dnsmasq
                exit 0
                fi
            fi
        fi

# If ping fails

# Log failed attempt and increment the counter
        COUNTER=$((COUNTER + 1))
        logger -t "$TAG" "Ping to Android failed... (attempt $COUNTER)"
    
# Wait before the next attempt
        logger -t "$TAG" "Waiting 60 seconds before the next attempt..."
        sleep 60

done

# If all pings fail...
logger -t "$TAG" "All Android ping tests have failed. Checking WG Server....."

        ENABLED=$(nvram get "$IF"_enable)
        if [ -z "$2" ] || [ -z "$ENABLED" ] || [ "$ENABLED" -ne "2" ] ; then
        logger -t "$TAG" "Wireguard server already active..."
        exit 0

            else
            logger -t "$TAG" "Activating Wireguard server."
            nvram set wgs1_enable=1
            service restart_dnsmasq
            exit 0
        fi

Thank you to bg604 and ZebMcKayhan for providing scripts as starting points for me. Im not sure if this really belongs in its own thread. I thought i would ask here as its pretty similar to what the OP has achieved.

I think iv made a mistake in the "#If ping succeeds" if statement. The script runs as it is with the following:

wg-server-ctrl-v1: Checking for Android phone...
wg-server-ctrl-v1: Android ping attempt 1
wg-server-ctrl-v1: Android device detected.
wg-server-ctrl-v1: Wireguard Server already deactivated.

But my wireguard server is switched on where the script detects that it isnt. Apologies, my scripting isnt great, iv just cobbled together things.

I think the if statement is wrong where if the ping is succeeds then get the status of interface wgs1 as either 0 for off or 1 for on and then based on that continue. I think the values are getting mixed up here somewhere.

Thank you for any and all help.

Noob.
 
@Net Noob How are you running this to test it? What do you expect to be in $1 and $ENABLED ? As it's currently written the "Deactivating WG Server..." section would never be executed.

I suggest you rewrite the following section with the correct indentation to make it easier to understand the flow.

Code:
# Ping the target
        ping -c 1 -w 1 192.168.50.241 > /dev/null 2>&1
        if [ "$?" -eq 0 ]; then                                # If ping succeeds
            ENABLED=$(nvram get "$IF"_enable)
            if [ -z "$1" ] || [ -z "$ENABLED" ] || [ "$ENABLED" -ne "1" ] ; then
                logger -t "$TAG" "Android device detected."
                logger -t "$TAG" "Wireguard Server already deactivated."
                exit 0
            else
                if [ -z "$1" ] ; then
                    logger -t "$TAG" "Android device detected."
                    logger -t "$TAG" "Deactivating WG Server..."
                    nvram set wgs1_enable=0
                    service restart_wgs
                    service restart_dnsmasq
                    exit 0
                fi
            fi
        fi
 
Last edited:
if [ -z "$2" ] || [ -z "$ENABLED" ] || [ "$ENABLED" -ne "2" ]
I get $1 is 1 for wgs1, but there is only 1 server in the router, so it may as well be hardcoded so you don't need to use it. But in this last if statement there is a check for $2 which don't exist anywhere else. If you don't use it when calling the script it will be empty.

Also, I think wgs1_enable is 0 or 1 but never 2. Or where did you get that information?

I propose you hardcode wgs1 and remove all checks regarding $1 and see where that gets you. Also remove any checks for $2 if you don't use it.

I commonly makes use of echo during development to print variable content before statements that don't appear to work for debugging. Ie
Code:
echo "2nd arg = $2"
echo "ENABLED = $ENABLED"

I'm struggling with script syntax as well and spends more time that I would like to admit to get these stuff working.
 

Support SNBForums w/ Amazon

If you'd like to support SNBForums, just use this link and buy anything on Amazon. Thanks!

Sign Up For SNBForums Daily Digest

Get an update of what's new every day delivered to your mailbox. Sign up here!
Back
Top