URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID1
Нить номер: 74056
[ Назад ]

Исходное сообщение
"Скрипт на perl для автоматического переключения на резервный канал"

Отправлено SergeyKa , 14-Май-07 17:16 
Просто хочу поделится :)


Система FreeBSD 5.5

Требуется установить 2 файла в /usr/local/etc/rc.d c правами 555

# cat /usr/local/etc/rc.d/reserv.sh

#!/bin/sh

case "$1" in
start)
        [ -x /usr/local/etc/rc.d/reserv.pl ] && /usr/local/etc/rc.d/reserv.pl && echo -n ' reserv'
        ;;
stop)
        [ -r /var/run/reserv.pl.pid ] && kill -s TERM `cat /var/run/reserv.pl.pid` > /dev/null && echo -n ' reserv'
        ;;
*)
        echo "Usage: `basename $0` {start|stop}" >&2
        ;;
esac

exit 0


Собственно сам скрипт, в котором нужно поменять гетвеи на ваши

#!/usr/bin/perl

use File::Basename;
use Sys::Syslog qw(:DEFAULT setlogsock);
use Proc::Daemon;
use strict;
use warnings;

my $me = basename($0);
my $pidfile = "/var/run/$me.pid";
if ( -e $pidfile ) {
    print "Script is runing! Exist $pidfile";
    exit;
}

my $alert_email = "robot\@my.ru";
my $from = "robot\@my.ru";

my $check;

my $ext_gw_a    = "x.x.x.x";
my $ext_gw_b    = "z.z.z.z";

my $cmd_ping = "/sbin/ping -q -c 2";
my $cmd_mail="/usr/sbin/sendmail -t";

sub ping {
  my ($host) = @_;
  my $ping_output = `$cmd_ping $host`;
  if ($ping_output =~ /100\% packet loss/){
    return 0;
  } else {
    return 1;
  }
}

sub send_mail {
  my ($subj) = @_;
  open (SENDMAIL, "|$cmd_mail") || syslog('warning', "Can not run sendmail - %m");
  print SENDMAIL "MIME-Version: 1.0\n";
  print SENDMAIL "Content-Type: text/plain; charset=\"koi8-r\"\n";
  print SENDMAIL "Content-Transfer-Encoding: 8bit\n";
  print SENDMAIL "To: $alert_email\n";
  print SENDMAIL "From: MONITORING $from\n";
  print SENDMAIL "Subject: ALERT: $subj\n\n";
  close (SENDMAIL);
}

sub change_dg {
    my ($defg) = @_;
    my $time = scalar localtime;
    my $soobsh = "Switch $defg / $time";
    my $cmd_netstat = '/usr/bin/netstat -nr |grep default';
    my $DGB=`$cmd_netstat`;
    unless ($DGB =~ /$defg/) {
        system("route delete default");
        system("route add default $defg");
        syslog('info', $soobsh);
        send_mail($soobsh);
    }
}

Proc::Daemon::Init;

open (PID,">$pidfile") || die "cannot create pidfile $!";
print PID $$;
close (PID);

setlogsock('unix');
openlog ('rezerv', 'ndelay,pid', 'local0');
syslog('info', 'Starting rezerv test');

$SIG{INT} = \&SHUTDOWN;
$SIG{TERM} = \&SHUTDOWN;

my ($prow1,$prow2);
for (;;) {
    # Check channel
    if (ping($ext_gw_a)) {
        $prow1=1;
    }else{
        $prow1=0;
    }
    if (ping($ext_gw_b)) {
        $prow2=1;
    }else{
        $prow2=0;
    }

    if ($prow1 && $prow2) {
        change_dg($ext_gw_a);
    }
    if ($prow1 && !$prow2) {
        change_dg($ext_gw_a);
    }
    if (!$prow1 && $prow2) {
        change_dg($ext_gw_b);
    }
    sleep(40);
}

sub SHUTDOWN() {
    unlink($pidfile);
    closelog();
    exit;
}


Буду рад коментариям :)


Содержание

Сообщения в этом обсуждении
"Скрипт на perl для автоматического переключения на резервный..."
Отправлено YuryD , 15-Май-07 08:09 
>Просто хочу поделится :)
>
>
>Буду рад коментариям :)


  Замечания -  не везде прописаны полные пути к системным утилитам grep и route


"Скрипт на perl для автоматического переключения на резервный..."
Отправлено SergeyKa , 16-Май-07 17:51 
Вот конечный вариант - более продвинутый :)
Изменился только

#!/usr/bin/perl

use File::Basename;
use Sys::Syslog qw(:DEFAULT setlogsock);
use Proc::Daemon;
use strict;
use warnings;

my $me = basename($0);
my $pidfile = "/var/run/$me.pid";
if ( -e $pidfile ) {
    print "Script is runing! Exist $pidfile";
    exit;
}

my $alert_email = "my\@my.ru";
my $from = "my\@my.ru";

my $check;

my $ext_gw_a    = "x.x.x.x";
my $ext_gw_b    = "y.y.y.y";

my $curent_gw   = $ext_gw_a;

my $cmd_ping = "/sbin/ping -q -c 2";
my $cmd_mail="/usr/sbin/sendmail -t";

# mail.ru 194.67.57.26
# f.root-servers.net 192.5.5.241
# ya.ru 87.250.251.8
# rambler.ru 81.19.70.3
# google.com 64.233.167.99

my @targets = ('194.67.57.26','192.5.5.241','87.250.251.8','81.19.70.3','64.233.167.99');


sub ping {
  my ($host) = @_;
  my $ping_output = `$cmd_ping $host`;
  if ($ping_output =~ /100\% packet loss/){
    return 0;
  } else {
    return 1;
  }
}

sub send_mail {
  my ($subj) = @_;
  open (SENDMAIL, "|$cmd_mail") || syslog('warning', "Can not run sendmail - %m");
  print SENDMAIL "MIME-Version: 1.0\n";
  print SENDMAIL "Content-Type: text/plain; charset=\"koi8-r\"\n";
  print SENDMAIL "Content-Transfer-Encoding: 8bit\n";
  print SENDMAIL "To: $alert_email\n";
  print SENDMAIL "From: MONITORING $from\n";
  print SENDMAIL "Subject: ALERT: $subj\n\n";
  close (SENDMAIL);
}

sub change_dg {
    my ($defg) = @_;
    my $time = scalar localtime;
    my $soobsh = "Switch $defg / $time";
    my $cmd_netstat = '/usr/bin/netstat -nr |/usr/bin/grep default';
    my $DGB=`$cmd_netstat`;
    unless ($DGB =~ /$defg/) {
        system("/sbin/route delete default");
        system("/sbin/route add default $defg");
        syslog('info', $soobsh);
        send_mail($soobsh);
    }
}

Proc::Daemon::Init;

open (PID,">$pidfile") || die "cannot create pidfile $!";
print PID $$;
close (PID);

setlogsock('unix');
openlog ('rezerv', 'ndelay,pid', 'local0');
syslog('info', 'Starting rezerv test');

$SIG{INT} = \&SHUTDOWN;
$SIG{TERM} = \&SHUTDOWN;

# При старте задаём провайдера №1 (по умолчанию)
change_dg($ext_gw_a);

my ($prow1,$prow2,$up_hosts);
for (;;) {
    # Проверяем работу шлюзов провайдеров
    if (ping($ext_gw_a)) {
        $prow1=1;
    }else{
        $prow1=0;
    }
    if (ping($ext_gw_b)) {
        $prow2=1;
    }else{
        $prow2=0;
    }
    # Выясняем есть ли смысл пинговать удалённые хосты (если шлюз неработает - не пингуем)
    if ((($curent_gw =~ /$ext_gw_a/) && ($prow1)) or (($curent_gw =~ /$ext_gw_b/) && ($prow2))) {
        foreach my $host (@targets) {
            $up_hosts++ if ping($host);
        }
    }
    
    # Переключение на рабочего провайдера
    if ($curent_gw =~ /$ext_gw_a/ ) {
        if (!$prow1 or !$up_hosts){
            if ($prow2) {
                change_dg($ext_gw_b);
                $curent_gw=$ext_gw_b;
            }
        }
    }
    if ($curent_gw =~ /$ext_gw_b/ ) {
        if (!$prow2 or !$up_hosts){
            if ($prow1) {
                change_dg($ext_gw_a);
                $curent_gw=$ext_gw_a;
            }
        }
    }

    # Переключение на провайдера по умолчанию если он стал вновь доступен
    if (($curent_gw =~ /$ext_gw_b/ ) && ($prow1)) {
        change_dg($ext_gw_a);
        $curent_gw=$ext_gw_a;
    }
    sleep(40);
}

sub SHUTDOWN() {
    unlink($pidfile);
    closelog();
    exit;
}