Под хабракатом приведены примеры скриптов, упрощающие жизнь :)
В своё время у Акадо наблюдались проблемы с авторизацией pppoe.
И поскольку при загрузке системы часть демонов привязывалась к получаемому ip адресу, то нужно было как-то автоматизировать процесс загрузки системы и исключить ситуацию простоя.
Идея заключалась в том, чтоб после запуска pppd проверять полученный от провайдера адрес.
Сам скрипт представляет из себя следующее:
и добавлен в /etc/rc.d/ppp.
Если не удалось получить требуемый адрес, то отправляем машинку в ребут.
Почему не пытаемся перезапустить сам демон ppp?
К моменту проверки ещё не многое запущено, поэтому исключаем версию о том, что перезагрузка будет долгой — до момента остановки процессов, а усложнять конструкцию очень не хотелось.
Помимо описанной выше ситуации могут случиться проблемы с потерей соединения.
Хочу оговориться, что полёт пакетов происходит след. образом:
Скрипт запускается по крону с периодом в 10 минут и если пинг неудачен до внутренних адресов, то пытаемся переполучить адрес от dhcp, до внешних — рестартим pppd.
Не забываем подставить свои значения проверяемых внутренних ресурсов (см. определение массива @check_ips).
В /var/log/ifaces.log можем отслеживать проблемы.
Само собой, можно было убрать использование модуля Touch и по иному описать часть операций, но мне в момент написания хотелось именно так :)
P.S.: используется FreeBSD, Perl 5.10.
Перл 5.8 будет ругаться на использование threads->list(threads::all).
Часть 1. Проверка получаемого адреса
В своё время у Акадо наблюдались проблемы с авторизацией pppoe.
И поскольку при загрузке системы часть демонов привязывалась к получаемому ip адресу, то нужно было как-то автоматизировать процесс загрузки системы и исключить ситуацию простоя.
Идея заключалась в том, чтоб после запуска pppd проверять полученный от провайдера адрес.
Сам скрипт представляет из себя следующее:
i=0
pppip="<my_ip>"
echo -e "waiting pppoe connection"
until [ "$i" -eq "30" ]
do
iconf=`/sbin/ifconfig tun0 | awk '/inet/ {print $2}'`
if [ "$iconf" = "$pppip" ]
then
echo -e "successful"
i="30"
break
else
i=`expr $i + 1`
echo -n "."
sleep 5
fi
done
if [ "$iconf" != "$pppip" ]
then
echo -e "pppoe not connected!\nSystem will be reboot"
reboot
fi
и добавлен в /etc/rc.d/ppp.
Если не удалось получить требуемый адрес, то отправляем машинку в ребут.
Почему не пытаемся перезапустить сам демон ppp?
К моменту проверки ещё не многое запущено, поэтому исключаем версию о том, что перезагрузка будет долгой — до момента остановки процессов, а усложнять конструкцию очень не хотелось.
Часть 2. Проверка соединения
Помимо описанной выше ситуации могут случиться проблемы с потерей соединения.
Хочу оговориться, что полёт пакетов происходит след. образом:
- для работы локальной сети используется адрес, выдаваемый от dhcp сервера провайдера;
- для выхода во вне используется pppoe.
Скрипт запускается по крону с периодом в 10 минут и если пинг неудачен до внутренних адресов, то пытаемся переполучить адрес от dhcp, до внешних — рестартим pppd.
#!/usr/bin/perl use strict; use warnings; use threads; use Touch; use Net::Ping; use Net::Ifconfig::Wrapper qw(Ifconfig); my @check_hosts = qw/ya.ru google.com/; my @check_ips = qw/172.18.1.1 172.18.1.2/; my $int_if = 're0'; my $ext_if = 're1'; sub get_ips { my ($iface) = @_ ; my @ifaces = (); my $info = Ifconfig('list', '', '', ''); unless ( defined($info->{$iface}) ) { die "Couldn't find ip address on $iface\n"; } for ( sort keys %{$info->{$iface}{'inet'}} ) { push(@ifaces,$_); } if ( scalar(@ifaces) > 0 ) { return \@ifaces; } else { return undef; } } sub ping_state { my ($dst_src,$proto,$iface) = @_; die "Check params in sub ping_state" unless ( defined($dst_src) && ref($dst_src) eq 'ARRAY' ); $proto = '' unless ( defined($proto) ); my $p = Net::Ping->new($proto); my $int_ips = undef; $int_ips = get_ips($iface) if ( defined($iface) ); $p->bind($int_ips->[0]) if ( defined($int_ips) ); my $i = 0; for my $sources ( @{$dst_src} ) { if ( $p->ping($sources,10) ) { $i++; last; } } $p->close(); if ($i > 0) { return 1; } else { return 0; } } sub do_log { my ($message,$log_file) = @_; $log_file = '/var/log/ifaces.log' unless ( defined($log_file) ); unless ( -e "$log_file" ) { touch($log_file) or die("Failed touch $log_file"); } open(LOG,">> $log_file"); my ($sec,$min,$hour,$mday,$mon,$year) = localtime(time); print LOG '[' . ($year+1900) . '-' . ( ( $mon < 10 ) ? ( '0'.$mon ) : $mon ) . '-' . ( ( $mday < 10 ) ? ( '0'.$mday ) : $mday ) . ' ' . ( ( $hour < 10 ) ? ( '0'.$hour ) : $hour ) . ':' . ( ( $min < 10 ) ? ( '0'.$min ) : $min ) . ':' . ( ( $sec < 10 ) ? ( '0'.$sec ) : $sec ) . ']' . "$message\n"; close LOG; } my $thr = threads->create(sub { unless ( ping_state(\@check_ips,'tcp',$int_if) ) { do_log("Check connect to LAN resources : failed"); system("dhclient $ext_if"); } }); unless ( ping_state(\@check_hosts,'icmp') ) { do_log("Check connect to WAN resources : failed"); opendir(RUN,'/var/run'); for ( grep {/tun\w+\.pid/} readdir(RUN) ) { open(PID,'/var/run/' . "$_"); local $/ = undef; my $pid = <PID>; close(PID); chop($pid); kill(9,$pid); } closedir(RUN); system("ppp -ddial akado"); } foreach my $t ( threads->list(threads::all) ) { $t->join(); }
Не забываем подставить свои значения проверяемых внутренних ресурсов (см. определение массива @check_ips).
В /var/log/ifaces.log можем отслеживать проблемы.
Само собой, можно было убрать использование модуля Touch и по иному описать часть операций, но мне в момент написания хотелось именно так :)
P.S.: используется FreeBSD, Perl 5.10.
Перл 5.8 будет ругаться на использование threads->list(threads::all).