What's new

WANFailover Dual WAN Failover Script

  • 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!

Uploaded an update guys, let me know if you find anymore issues or bugs. :)
 
Uploaded an update guys, let me know if you find anymore issues or bugs. :)
I dont even want to attempt to understand this :)
Code:
while \
  { [[ "$(nvram get wans_dualwan | awk '{print $2}')" == "none" ]] && [[ "$(nvram get wans_mode)" != "fo" ]] && [[ "$(nvram get wandog_enable)" != "0" ]] ;} \
      || { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_enable)" == "0" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_enable)" == "0" ]] ;} \
        || { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_state_t)" != "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_state_t)" != "2" ]] ;} \
          || { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_enable)" == "1" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_enable)" == "0" ]] \
          && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_state_t)" == "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_primary)" == "1" ]] ;} \
            || { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_enable)" == "0" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_enable)" == "1" ]] \
            && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_state_t)" == "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_primary)" == "1" ]] ;} \
                  || { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_enable)" == "1" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_enable)" == "1" ]] \
                  && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_state_t)" != "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_state_t)" != "2" ]] \
                  && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_realip_state)" != "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_realip_state)" != "2" ]] \
                  && [ -z "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_realip_ip)" ] && [ -z "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_realip_ip)" ] ;} \
                    || { [[ "$(ping -I $(nvram get $(echo $WANPREFIXES | awk '{print $1}')_ifname) $WAN0TARGET -c $PINGCOUNT -W $PINGTIMEOUT | grep -e "packet loss" | awk '{print $7}')" == "100%" ]] \
                    && [[ "$(ping -I $(nvram get $(echo $WANPREFIXES | awk '{print $2}')_ifname) $WAN0TARGET -c $PINGCOUNT -W $PINGTIMEOUT | grep -e "packet loss" | awk '{print $7}')" == "100%" ]] ;} >/dev/null;do
  # Return to WAN Status if Both WAN links were disabled and one is re-enabled and connected
  if  { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_enable)" == "1" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_enable)" == "0" ]] \
      && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_state_t)" == "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_primary)" == "1" ]] ;} \
        || { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_enable)" == "0" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_enable)" == "1" ]] \
        && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_state_t)" == "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_primary)" == "1" ]] ;} >/dev/null;then
 
I dont even want to attempt to understand this :)
Code:
while \
  { [[ "$(nvram get wans_dualwan | awk '{print $2}')" == "none" ]] && [[ "$(nvram get wans_mode)" != "fo" ]] && [[ "$(nvram get wandog_enable)" != "0" ]] ;} \
      || { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_enable)" == "0" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_enable)" == "0" ]] ;} \
        || { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_state_t)" != "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_state_t)" != "2" ]] ;} \
          || { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_enable)" == "1" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_enable)" == "0" ]] \
          && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_state_t)" == "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_primary)" == "1" ]] ;} \
            || { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_enable)" == "0" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_enable)" == "1" ]] \
            && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_state_t)" == "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_primary)" == "1" ]] ;} \
                  || { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_enable)" == "1" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_enable)" == "1" ]] \
                  && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_state_t)" != "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_state_t)" != "2" ]] \
                  && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_realip_state)" != "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_realip_state)" != "2" ]] \
                  && [ -z "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_realip_ip)" ] && [ -z "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_realip_ip)" ] ;} \
                    || { [[ "$(ping -I $(nvram get $(echo $WANPREFIXES | awk '{print $1}')_ifname) $WAN0TARGET -c $PINGCOUNT -W $PINGTIMEOUT | grep -e "packet loss" | awk '{print $7}')" == "100%" ]] \
                    && [[ "$(ping -I $(nvram get $(echo $WANPREFIXES | awk '{print $2}')_ifname) $WAN0TARGET -c $PINGCOUNT -W $PINGTIMEOUT | grep -e "packet loss" | awk '{print $7}')" == "100%" ]] ;} >/dev/null;do
  # Return to WAN Status if Both WAN links were disabled and one is re-enabled and connected
  if  { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_enable)" == "1" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_enable)" == "0" ]] \
      && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_state_t)" == "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_primary)" == "1" ]] ;} \
        || { [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_enable)" == "0" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_enable)" == "1" ]] \
        && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $2}')_state_t)" == "2" ]] && [[ "$(nvram get $(echo $WANPREFIXES | awk '{print $1}')_primary)" == "1" ]] ;} >/dev/null;then
In my testing I have found several conditions that called for the need of that big while loop, it has been the biggest pain of this whole thing....lol
 
I was just thinking, well Ranger is apparently drinking, im opening me a beer :)
Actually going to the gym soon, that's my stress reliever haha
 
…said no coder ever. :)
lol professionally I’m a Cyber Security Engineer / Systems Engineer so I only wear the coding hat on the side . But actually I love the gym a lot to be honest lol
 
I am glad to see this project progressing. Maybe some Asus models will finally have Dual WAN working as it should. I tried for awhile but gave up on the built in Dual WAN as it never worked correctly.
 
Last edited:
Installed this morning, everything seems to be working very well now.
I’m working on another minor release to cleanup that WANDisabled logic and make it cleaner and a couple other things but glad it is working well for you!
 
I am glad to see project this progressing. Maybe some Asus models will finally have Dual WAN working as it should. I tried for awhile but gave up on the built in Dual WAN as it never worked correctly.
Literally why I started this, the ASUS failover is terrible and annoyed me to no end…lol
 
I am glad to see project this progressing. Maybe some Asus models will finally have Dual WAN working as it should. I tried for awhile but gave up on the built in Dual WAN as it never worked correctly.
So far the new script is working perfect. I shut off and on my starlink router 4 times today, it takes around 3minutes to come back up. It switched back and forth correctly and fast. Also
having the ability to notify through log or email is a big plus. We all want to know when and how often it happens.
 
So far the new script is working perfect. I shut off and on my starlink router 4 times today, it takes around 3minutes to come back up. It switched back and forth correctly and fast. Also
having the ability to notify through log or email is a big plus. We all want to know when and how often it happens.
Speaking of logs, I am adding a log if some packet loss is experienced during monitor but not enough to cause failover to occur, you get a log saying “WAN has 33% packet loss” or etc. Just based on any pings being missed during the monitor running.
 
Speaking of logs, I am adding a log if some packet loss is experienced during monitor but not enough to cause failover to occur, you get a log saying “WAN has 33% packet loss” or etc. Just based on any pings being missed during the monitor running.
Published v1.3.5, you can update using the same command I put in the OP.

v1.3.5 Notes
General:
- Renamed WAN0Monitor to WAN0 Failover Monitor
- Renamed WAN0RestoreMonitor to WAN0 Failback Monitor
- Optimized WAN Disabled Logic.
- During WAN Status Check, it will look for 0.0.0.0 as a WAN interface's Gateway or IP Address and mark it as Disconnected.
- Updated logging Verbiage for Switch WAN.
- Moved DNS Resolv File Variable to Global Variables
- Added key events to go to System Log that can be displayed in the ASUS System Log Web GUI. This includes Failures, Primary WAN switching, and Packet Loss detection.

Monitor Mode:
- Monitor Mode will now not be killed by Kill Mode or Log Clean Mode

See Screenshots for Example Logs in ASUS System Log.
 

Attachments

  • Failover.png
    Failover.png
    48.6 KB · Views: 66
  • Failback.png
    Failback.png
    17 KB · Views: 67
Last edited:
Published v1.3.5, you can update using the same command I put in the OP.
...
- Added key events to go to System Log that can be displayed in the ASUS System Log Web GUI. This includes Failures, Primary WAN switching, and Packet Loss detection.
...
Bash:
SYSTEMLOGPATH="/tmp/syslog.log"
...
...
echo "$(date | awk '{print $2,$3,$4}') ${0##*/}: Returning to check WAN Status" >> $SYSTEMLOGPATH
...

There's a built-in interface to append messages to the system log via the /usr/bin/logger command (type logger --help for details).

Example call:
Bash:
logger -t "${0##*/}" "Returning to check WAN Status"

It's always recommended to use this built-in interface command rather than writing directly to the system log file because the native command encapsulates the implementation requirements needed to coordinate access to this shared system resource so that it can be used asynchronously by multiple concurrent processes and avoid "stepping on each other's toes."

For some projects I've worked on in the past, I've written library functions (in C, C++, C#, Java) to access specific shared resources within a system and, as a rule, some semaphore, lock, or mutex object is used to handle & coordinate access to the shared resource from multiple requests coming from multiple concurrent processes so that they all get timely read/write access without interfering with each other.

The point is that when a built-in interface command already exists, that is the preferred method to use if you want to be a "good citizen" when accessing a shared system resource.

Just my $0.02
 
Bash:
SYSTEMLOGPATH="/tmp/syslog.log"
...
...
echo "$(date | awk '{print $2,$3,$4}') ${0##*/}: Returning to check WAN Status" >> $SYSTEMLOGPATH
...

There's a built-in interface to append messages to the system log via the /usr/bin/logger command (type logger --help for details).

Example call:
Bash:
logger -t "${0##*/}" "Returning to check WAN Status"

It's always recommended to use this built-in interface command rather than writing directly to the system log file because the native command encapsulates the implementation requirements needed to coordinate access to this shared system resource so that it can be used asynchronously by multiple concurrent processes and avoid "stepping on each other's toes."

For some projects I've worked on in the past, I've written library functions (in C, C++, C#, Java) to access specific shared resources within a system and, as a rule, some semaphore, lock, or mutex object is used to handle & coordinate access to the shared resource from multiple requests coming from multiple concurrent processes so that they all get timely read/write access without interfering with each other.

The point is that when a built-in interface command already exists, that is the preferred method to use if you want to be a "good citizen" when accessing a shared system resource.

Just my $0.02
When I was initially trying logger it didn't seem to want to append to /tmp/syslog.log file, I will test some more and see if it works.
 
When I was initially trying logger it didn't seem to want to append to /tmp/syslog.log file, I will test some more and see if it works.
Tested again and now the logger works, I think sometimes these routers just make things difficult...lol Anyway, I patched the script and after you update to v1.3.7, you can run the command argument "update" with the script to update it to the latest version from my Repo. It will tell you if it is out of date and prompt you if you want to update.
 
When I was initially trying logger it didn't seem to want to append to /tmp/syslog.log file, I will test some more and see if it works.
Tested again and now the logger works, I think sometimes these routers just make things difficult...lol
Whenever you run into a coding issue with something that you know "it should just work" but can't quite figure out why it doesn't, don't be shy to ask for help on this forum. There are many shell script programmers here who are quite generous with their time and are willing to help out another fellow coder. Often times a second pair of eyes can help us "see through the fog" and eventually get a clearer view of the situation. You don't have to go completely solo on your coding journey.

Glad you got it 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!
Top