Shell Script for Auto IP Change

Hi,

I am newbie to Linux/Asterisk. I am trying to write a shell script that would look for my SIP trunk registration, if found UNREACHABLE then it would execute a command and check my local IP, if my local IP is 192.168.1.106 then it would change the IP to 192.168.1.150 and vice versa, after that issue the commands, network service restart and amportal restart.

I have written following so far, and just by the looks, it seems wrong. Any help would be highly appreciated. Thanks

#!/bin/bash
asteriskbin=`which asterisk`
interval=10
ippath=/sbin/ifconfig
ip1=192.168.1.106
ip2=192.168.1.150
trunk="siptrunk"
run=true
while [[ "$run" == "true" ]]; do
checktrunk=`$asteriskbin -rx �sip show peer $trunk� | grep Status | grep -wc OK`
if [[ $checktrunk == 0 ]]; then
echo �TEST Trunk Down�
else
echo �SIP trunk registration OK.�
whatip=`$ippath eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}'
if [[ $whatip == $ip1 ]]; then 
ifconfig eth0 $ip2
else
ifconfig eth0 $ip1
network service restart
amportal restart
fi
sleep $interval
done
exit 1

Any error messages? I can't really guess what exactly you are doing or intending here, so it's difficult to comment on the logic flow. There's a fi missing, maybe before network service restart . Some improvement opportunities, e.g. the grep/cut/awk pipes, jumped to my eye.

As I said earlier, my trunks go offline (UNREACHABLE) every few days. The only work around is to have the local IP change and do a restart of asterisk service and network service. Changing the local IP is fine for me as all my clients connect through the VPN.

Any help would be appreciated. I havent executed the script as yet, as I know there are some syntax errors. Currently this is what I have.

#!/bin/bash
asteriskbin="which asterisk"
interval=10
ippath=/sbin/ifconfig

ip1=192.168.1.106
ip2=192.168.1.150

trunk="siptrunk"
run=true
while [[ "$run" == "true" ]]; do
    checktrunk="$asteriskbin -rx �sip show peer $trunk� | grep Status | grep -wc OK"
    if [[ $checktrunk == 0 ]]; then
    echo "TEST Trunk Down"
    else
    echo "SIP trunk registration OK."

whatip="$ippath eth0 | grep 'inet addr:' | cut -d: -f2 | awk '{ print $1}"

if [[ $whatip == $ip1 ]]; then 
    ifconfig eth0 $ip2
else
    ifconfig eth0 $ip1
    network service restart
    amportal restart

fi
    sleep $interval
done
#exit

Again, there's a fi missing.
Do you want to restart the network only if changed to ip1, or in both cases changing to and fro?
Try

ifconfig eth0 |awk '/inet addr:/ {sub (/addr:/,"", $2); print $2}'
1 Like

Hi Rudi,

Thanks for your help. I would like the network to be restarted and then Asterisk, in both cases where IP is chaned from ip1 to ip2 or ip2 to ip1. Should I try this?

ifconfig eth0 |awk '/inet addr:/ {sub (/addr:/,"", $2); print $2}'

Yes. And check for the missing fi ! Its position is crucial for your logics.

1 Like

Thanks, sure I will add in the

fi

and will run the script tomorrow and share the results. Much appreciated!

In fact there are some problems with your code, but overall it looks quite OK. Lacking the tools you work with i cannot test it, though, so some general remarks is all the help i can give you.

asteriskbin=`which asterisk`

Basically, this is a good attempt at enhancing runtime security, but: either "asterisk" is already within the PATH, then your statement would be superfluous, or it is not - would your statement help that in any way?

The answer is: no. Most binaries in Unix have fixed places anyway, so your "asterisk" binary might always reside in "/usr/bin/asterisk" or so. If this is not the case and you really need to find out where it is, then your script should react in some way if it is not to be found. And, by the way: NEVER USE BACKTICKS! POSIX process substitution is done with "$(...)". Having said this, consider the following:

asteriskbin="$(which asterisk)"
if [ ! -x "$asteriskbin" ] ; then
     echo "ERROR: asterisk executable not available, aborting...." >&2
fi

Generally you should strive to use as few commands as possible, because every "fork()" system call is expensive. I do not know the output you are trying to check here, but i suppose it is "Status" and "OK" on the same line:

checktrunk=`$asteriskbin -rx �sip show peer $trunk� | grep Status | grep -wc OK`

Furthermore, you should ALWAYS quote your string variables. If "$asteriskbin" contains a space (this would be a legal filename in Unix) your commadn would not work any more. The following is a suggestion as to how this is done easier. Maybe you have to adjust the regular expression in "grep" if the output is not like i supposed it to be:

checktrunk=$("$asteriskbin" -rx "sip show peer $trunk" | grep -c "Status.*OK")

Another this is to try to work strictly typed, even if the shell is not requiring it. If you want to create an integer variable, then create one explicitly:

typeset -i interval=10

The following is a common misconception related to that:

if [[ $checktrunk == 0 ]]; then

"test" (and its built-in sibling "[[") is strictly distinguishing between string comparisons and integer comparisons. "==" is an operator for strings only. Because you want to compare the integer values of "0" and "$checktrunk" you have to use the integer equivalent, which is "-eq":

if [[ $checktrunk -eq 0 ]]; then

I hope these pointers help. If you need more support just call back.

bakunin

Hi RudiC,

Sorry for a delayed response. I have not yet tried the code as I have been able to narrow down the problem cause. However the solution to the problem is a quick reboot of router.

However I appreciate all your help and efforts.

Thanks!

---------- Post updated at 09:23 AM ---------- Previous update was at 08:58 AM ----------

Hi Bakunin,

Thanks for such an excellent explanation... has actually made me understand lot of things. I really appreciate the effort you have put through.

Your post has almost answered my next question... but just a small glitch.

checktrunk=$(asterisk -rx "sip show peer jdjdjdjd" | grep -c "Status.*OK")

always returns SIP trunk registration OK. even though I have put an incorrect SIP trunk name in the above checktrunk variable.

---------- Post updated at 09:56 AM ---------- Previous update was at 09:23 AM ----------

#!/bin/bash
typeset -i interval=5
run=true
trunk=vonage
while [[ "$run" == "true" ]]; do
checktrunk=$(asterisk -rx "sip show peer $trunk" | grep -c "Status.*OK")
if [[ $checktrunk -eq 0 ]]; then
echo "SIP trunk registration failed."
else
echo "SIP trunk registration OK."
fi
sleep $interval
done
exit 1

Surprised! this is working exactly the way i want it to work!

it returns SIP trunk registration failed. when the trunk is down and returns SIP trunk registration OK. otherwise.

Problem solved! Thanks a lot bakunin & RudiC :slight_smile: