bash script to change dns on ping fail

Discussion in 'Programming/Scripts' started by K_meleonu, May 1, 2013.

  1. K_meleonu

    K_meleonu Member

    Hello to all,
    It seems today i am a little or more stupid.
    I am trying to write a bash script wich should change the actual dns servers with new ones if ping geths ping: unknown host domain.com or a loss ower 20% or ping fails.

    If is someone here who wants to help me or knows a script to do what i nees please post it here.
    Will be much apreciate.

    Thank you all in advance.

    P.S.
    The script i wrote and does now work is:
    Code:
    #!/bin/bash
    PING=`ping -c 5 yahoo.com | grep packets | awk '{print $1 $4 $6}' | cut -c 1-3`;
    RASPUNS="550";
    DNSACT=`tail -n 2 /etc/resolv.conf`;
    DNS1=`cat dns1 > /etc/resolv.conf`;
    DNS2=`cat dns2 > /etc/resolv.conf`;
    DNNS1=`cat dns1`;
    DNNS2=`cat dns2`;
    if [ "$PING" -ne "$RASPUNS" ];
    then
    {
    if ["$DNSACT" = "$DNS1"]
    then {
    echo $DNS2;
    }
    else {
    echo $DNS1;
    }
    fi
    }
    else
    {
    echo "yahoo.com raspunde";
    }
    fi
    
    in file dns1 i have nameserver x.x.x.x and nameserver x.x.x.y
    in file dns2 i have nameserver w.w.w.w and nameserver w.w.w.q

    This script should do the following:
    ping 5 times yahoo.com. If the result is not equal with 550 (means 5 packets sent, 5 packets received and 0% loss) it check's if actual dns servers are the same with the dns servers from dns1 file.
    If they are the same the script should put in /etc/resolv.conf the dns servers from file dns2. If they are not the same the script should put in /etc/resolv.conf the dns servers from dns1 file.
     
  2. K_meleonu

    K_meleonu Member

    Hello again to all,
    I have modifyed the script to this:
    Code:
    #!/bin/bash
    PING=`ping -c 5 yahoo.com | grep packets | awk -F% '{print $1 $4 $6}' | cut -c 36-38`;
    RASPUNS="20";
    DNSACT=`tail -n 2 /etc/resolv.conf`;
    DNNS1=`cat dns1`;
    DNNS2=`cat dns2`;
    if [[(" $PING" > "$RASPUNS") || ("$DNSACT" = "$DNS1")]];
    then
    {
    cat dns2 > /etc/resolv.conf;
    }
    else 
    {
    cat dns1 > /etc/resolv.conf;
    }
    fi
    
    It works fine exceptin when the ping answer is ping: unknown host yahoo.com. If i receive this answer the script terminates and doen not change the dns servers.

    Still waiting for some help.
    Thank you all in advance
     
    Last edited: May 1, 2013
  3. sjau

    sjau Local Meanie Moderator

    here's a bit an improved version (bash-wise)

    Code:
    #!/bin/bash
    # Don't use ALLCAPS for custom variables. By convention only Environmental vars are ALLCAPS
    makeping=$(ping -c 5 "yahoo.com" | grep "packets" | awk -F% '{print $1 $4 $6}' | cut -c 36-38)
    raspuns="20";
    
    dnsact=$(tail -n 2 "/etc/resolv.conf")
    dnns1=$(cat dns1)
    dnns2=$(cat dns2)
    
    if [[ "${makeping}" -gt "${raspuns}" || "${dnsact}" = "${dns1}" ]]
    then
        cat "dns2" > "/etc/resolv.conf"
    else 
        cat "dns1" > "/etc/resolv.conf"
    fi
    
    As for the problem, I have no idea.
     
  4. K_meleonu

    K_meleonu Member

    Thank you for your reply and improvement. For me, the script worked even witll all caps (tested on ubuntu 12.0.4 LTS, Mandriva 2010 / 2011, Fedora 16).
    The problem for wich i didn't found a solution yet is the one stated in the post above. If the answer is unknown host the script stops.
    The only solution i found is to modify the host (in this case yahoo.com) with an IP address. But if that IP of yahoo.com fails then i will get a false response.
    If i use the host, even if the IP fails at first check, at the second check the IP will be another one.

    Again thank you for the improvement.

    Best regards
     
  5. sjau

    sjau Local Meanie Moderator

    as said, you shouldn't use ALLCAPS on vars. Also use $() to run commands instead of backticks.
     
  6. K_meleonu

    K_meleonu Member

    Here is the solution

    Code:
    #!/bin/bash
    PING=`ping -c 5 yahoo.com | grep packets | awk -F% '{print $1 $4 $6}' | cut -c 36-38`;
    RASPUNS="20";
    DNSACT=`tail -n 2 /etc/resolv.conf`;
    DNNS1=`cat dns1`;
    DNNS2=`cat dns2`;
    if [[(" $PING" > "$RASPUNS") || ("$DNSACT" = "$DNS1")]];
    then
    {
    cat dns2 > /etc/resolv.conf;
    }
    else
    {
    cat dns1 > /etc/resolv.conf;
    }
    fi
    
    
    This script will ping yahoo.com 5 times. If the ping result shows a loos ower 20% it will change the DNS servers.
    You will have to create 2 files named dns1 and dns2 in wich you have to write your nameserver x.x.x.x and nameserver y.y.y.y and nameserver x.x.x.x-alternative and nameserver y.y.y.y-alternative and run the script into a cron job.
     
  7. Marios Zindilis

    Marios Zindilis New Member

    Here's a potential problem with the script: ping performs two DNS resolutions during its operation:
    1. resolves yahoo.com to an IP, then
    2. resolves that IP back to a fully qualified domain name.

    For example:
    Code:
    marios@yovan ~ $ ping -c 1 yahoo.com
    PING yahoo.com (206.190.36.45) 56(84) bytes of data.
    64 bytes from ir1.fp.vip.gq1.yahoo.com (206.190.36.45): icmp_req=1 ttl=49 time=306 ms
    
    --- yahoo.com ping statistics ---
    1 packets transmitted, 1 received, 0% packet loss, time 0ms
    rtt min/avg/max/mdev = 306.046/306.046/306.046/0.000 ms
    You can see that ping resolved yahoo.com to 206.190.36.45 and then resolved again 206.190.36.45 to ir1.fp.vip.gq1.yahoo.com (the FQDN).

    If by coinsidence, the FQDN contains the word "packets", this will throw off your grep. So a small improvement to your script would be to add the -q option to ping (stands for "quiet"), so that the output is only the summary lines:
    Code:
    marios@yovan ~ $ ping -q -c 5 yahoo.com
    PING yahoo.com (98.139.183.24) 56(84) bytes of data.
    
    --- yahoo.com ping statistics ---
    5 packets transmitted, 5 received, 0% packet loss, time 4003ms
    rtt min/avg/max/mdev = 180.680/221.430/286.038/42.478 ms
    
     
  8. K_meleonu

    K_meleonu Member

    Hello there,
    You are right but you can also use ping 8.8.8.8 (google dns) or other yahoo.com or google.com IP address instead of domain name.
     

Share This Page