LinuxForum.Fans
Тема

bash скрипт, подскажите

Автор: sotariz 15 сообщений 5660 просмотров
#336098

Всем привет!
Задался вопросом от безделья, хочу написать скрипт который бы проверял доступность канала и при его отсутствии переходил бы на другой. Что имеем - два канала подключены на разные роутеры, оба роутера подключены к "балансеру", на балансере для того что бы сменить канал реализовал двух пользователей в профайле которых приписаны команды смены дефолтного гейтвея, удаления маскарадинга на одном интерфейсе и поднятия маскарадинга на другом.

text
#Change route to master provider
/sbin/ip route replace default via 192.168.2.3 dev eth1
/sbin/iptables -t nat -D POSTROUTING 1
/sbin/iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
#Change route to second provider
/sbin/ip route replace default via 192.168.3.3 dev eth0
/sbin/iptables -t nat -D POSTROUTING 1
/sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

Дабы отстранить пользователей от заморачивания с регистрацией пользователей на "балансере" с целью переключения на предположительно рабочий канал и хочу написать скрипт, а т.к. офис удаленный да еще и круглосуточный сам я эти действия выполняю крайне редко и не очень радует когда в ночной смене пользователь который умеет только что в чате писать да по телефону звонить... в общем такие индивидуумы сначала будят своего начальника, а потом меня...
То что пока осмыслил и написал:

text
#!/bin/bash
HOME=/home/sotariz/bin/changer
DATE=`/bin/date +%Y.%m.%d`
LOSTGW="0"
VPN_GW="10.0.0.1"
ROUTE_STATE="0"

ping -c 10 $VPN_GW > $HOME/ping_gw.log LOSTGW=$(cat $HOME/ping_gw.log | tail -n2 | head -n1 | awk {'print $6'} | sed s/%//) route -rn > $HOME/route.log ROUTE_STATE=$(cat $HOME/route.log | head -n3 | tail -n1 | awk {'print $2'})

Дальше, как мне кажется, должно следовать if [ $ROUTE_STATE="192.168.2.3" ] then goto туда else goto сюда fi
Суть вопроса - как реализовать блоки goto? Да, можно было бы ограничится написанием нужных действий в then и else, но хочется сделать блоки к которым был бы переход по goto

#336102

Никаких goto в bash нет. И очень надеюсь, что никогда не будет. В вашем случае следует использовать функции. Опишите их в скрипте да и вызывайте по имени в случае надобности.

#336104
"sotariz" написал:
ping -c 10 $VPN_GW > $HOME/ping_gw.log
LOSTGW=$(cat $HOME/ping_gw.log | tail -n2 | head -n1 | awk {'print $6'} | sed s/%//)

Я бы заменил хотя бы на

text

LOSTGW=$(ping -qw5 $VPN_GW | grep -oP "\d+%" | sed s/%//)

Если нужна автоматизация, то, наверное, бесконечный цикл с проверкой из которого вызывается ф-ция переключатель. А goto здесь ни к чему.

#336109
-=Serj=- написал:
Если нужна автоматизация, то, наверное, бесконечный цикл с проверкой

Я бы затолкал обычный, незацикленный скрипт в cron с проверкой раз в пять минут ;-)

#336110
"yars" написал:
Я бы затолкал обычный, незацикленный скрипт в cron с проверкой раз в пять минут ;-)

Ну или так, да :)

#336113

Мужики, я не силен еще в написании подобных скриптов... взялся с целью увеличения рюкзака со знаниями...
Вот что получилось сейчас:

text
#!/bin/bash   
#
#       Change route to First provider
#       /sbin/ip route replace default via 192.168.2.3 dev eth1
#       /sbin/iptables -t nat -D POSTROUTING 1
#       /sbin/iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
#
#       Change route to Second provider
#       /sbin/ip route replace default via 192.168.3.3 dev eth0
#       /sbin/iptables -t nat -D POSTROUTING 1
#       /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
#

[begin]

HOME=/home/sotariz/bin/changer DATE=`/bin/date +%Y.%m.%d` LOSTGW="0" VPN_GW="10.0.0.1" ROUTE_STATE="0" ROUTE_N2.3="First" ROUTE_N3.3="Second"

mkdir -p $HOME

ping -c 10 $VPN_GW > $HOME/ping_gw.log LOSTGW=$(cat $HOME/ping_gw.log | tail -n2 | head -n1 | awk {'print $6'} | sed s/%//) route -rn > $HOME/route.log ROUTE_STATE=$(cat $HOME/route.log | head -n3 | tail -n1 | awk {'print $2'})

if [ $LOSTGW="100" ] then if [ $ROUTE_STATE="192.168.2.3" ] then /sbin/ip route replace default via 192.168.3.3 dev eth0 /sbin/iptables -t nat -D POSTROUTING 1 /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE echo | date +"%T %d.%m.%Y"." Route change to ${ROUTE_N3.3}" >> $HOME/$DATE.status.log else /sbin/ip route replace default via 192.168.2.3 dev eth1 /sbin/iptables -t nat -D POSTROUTING 1 /sbin/iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE echo | date +"%T %d.%m.%Y"." Route change to ${ROUTE_N2.3}" >> $HOME/$DATE.status.log fi fi

exit 0

Походив по тропкам предложенным в google узнал что таки goto в bash отсутствует и советуют использовать функции, от сих вопрос как бы после выполнения того или иного условия сделать sleep после которого вернутся в начало к выполнению ping'а

#336115
"yars⇓" написал:
Я бы затолкал обычный, незацикленный скрипт в cron с проверкой раз в пять минут ;-)

ну я так и делаю обычно, но вот захотелось узнать и другую возможность :)

#336119

Цикл делай, в котором всегда будешь возврящаться в начало. И паузу можешь командой sleep делать.

#336120

Vascom, не сочтите за наглость, но как это сделать?..

#336121

Вот:

text

while true; do
    something
done
#336124

yars, спасибо. Вроде как разобрался вот только источники из google говорят что надо писать while [ состояние ] что писать в моем случае? или достаточно true;? Вразумите пожалуйста...

text
check ()
{
        ping -c 10 $VPN_GW > $HOME/ping_gw.log
        LOSTGW=$(cat $HOME/ping_gw.log | tail -n2 | head -n1 | awk {'print $6'} | sed s/%//)
        route -rn > $HOME/route.log
        ROUTE_STATE=$(cat $HOME/route.log | head -n3 | tail -n1 | awk {'print $2'})

if [ $LOSTGW="100" ] then if [ $ROUTE_STATE="192.168.2.3" ] then /sbin/ip route replace default via 192.168.3.3 dev eth0 /sbin/iptables -t nat -D POSTROUTING 1 /sbin/iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE echo | date +"%T %d.%m.%Y"." Route change to ${ROUTE_N3.3}" >> $HOME/$DATE.status.log else /sbin/ip route replace default via 192.168.2.3 dev eth1 /sbin/iptables -t nat -D POSTROUTING 1 /sbin/iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE echo | date +"%T %d.%m.%Y"." Route change to ${ROUTE_N2.3}" >> $HOME/$DATE.status.log fi fi }

while do check slepp ${TIMEOUT} done

#336152

man true говорит, что достаточно. Но можно и while 1; do ... done, неважно ;-) Ещё man bash и bash scripting guide почитайте до полного просветления.

#336165

Спасибо, взялся пока за чтиво предложенной вами же в соседней теме "Искусство программирования на языке сценариев командной оболочки". И уже с первых страниц решил что не будет ошибкой написать

text
while [ 1 ]
do
      check
      sleep ${TIMEOUT}
done
#336168
sotariz написал:
на балансере для того что бы сменить канал реализовал двух пользователей в профайле которых приписаны команды смены дефолтного гейтвея, удаления маскарадинга на одном интерфейсе и поднятия маскарадинга на другом.

По жирному - не плодите сущностей без надобности. Всё переключение каналов делается элементарно и под одним (рутом) пользователем. И циклов тоже никаких не требуется, достаточно "анализатор-коммутатор" запускать из-под крона, по расписанию.
Алгоритм работы простой:
1. Пингуем хост, который доступен только по дефолтному маршруту, например, роутер или DNS провайдера. Если хост доступен, то проверяем ранее запомненный флажок об доступности этого хоста на предыдущей итерации. Если всё нормально, то устанавливаем флажок (файл) и выходим. Если провайдер "воскрес" - устанавливаем настройки по дефолту, устанавливаем флажок и выходим.
2. Если дефолтный маршрут не доступен, проверяем резервный канал. Если резервный канал доступен, то устанавливаем резервные настройки, правим флажок и выходим. Если уже сидим на резервном канале - то ничего не делаем и просто выходим.

Вот и все действия для автоматической коммутации каналов. Никаких дополнительных юзеров и циклов. Примитивный проверочный скрипт, вызываемый по крону, раз в минуту. Хотя, если есть нужда проверять каналы чаще, чем раз в минуту, то без цикла со слипом не обойтись.
=================
Да, и по Вашему скрипту - он будет переключать каналы с основного на резервный только в том случае, если основной ляжет (100% потерь пакетов в нём, хотя я проверял бы код возврата пинга , 0 - всё хорошо, пинги ходят, не 0 - проблемы имеем). А как быть, если канал восстановится? Как вернуть состояние взад? Ведь по Вашей логике получается, что для этого нужно, чтобы рухнул резервный канал (если маршрут до VPN_GW - дефолтный)... А если он не рухнет?

#336231

Cruiser78, видимо вы не до конца поняли момент Что имеем:

text

[Internet----vpn1]----[174.174.174.29 router1 192.168.2.3]----[192.168.2.4 balance 192.168.3.4]----[192.168.3.3 router2 85.85.85.58]----[vpn2----internet]
                                                              [          192.168.1.3          ]

Каналы взамозаменяемые, vpn сервера разные но настроены одинаково. На каждом из роутеров действует скрипт который каждые 30 минут проверяет доступность канала по 3 адресам (гугль, впн, провайдер) и если все из бэд перегружает роутер(было выявлено что перезапуск сети + сервиса openvpn не всегда дает положительный результат, точнее почти всегда бесполезное занятие). Локалка, как можно догадаться находится за balance на интерфейсе 1.3. Дальше что бы пользователи сами могли менять канал при надобности и были сделаны два пользователя.

"sotariz⇓" написал:
в ночной смене пользователь который умеет только что в чате писать да по телефону звонить

и такому давать рут доступ? я хочу как можно реже о них думать, а вы предлагаете мне туда переехать видимо...

"Cruiser78⇓" написал:
Да, и по Вашему скрипту - он будет переключать каналы с основного на резервный только в том случае, если основной ляжет

Совершено верно, но опять таки оговорюсь что тут в принципе нет понятия основной-резервный

Войдите или зарегистрируйтесь, чтобы ответить.