где-так
у меня работает без сбоев уже долгое время. ограничения - нужно наличие валидного ключа. читаем внимательно комментарии в тексте, правим нужные места для себя.
адреса областей обновлений для конкретной версии нужно брать из update.drl
вешаем в cron по расписанию.
!!!обязательно собрать строку запроса - 60 позиция и ниже!!!#!/usr/bin/perl
# (c) 2004-2010 year by Ruslan G. Smirnoff
# ver.20100322.1230
use String::CRC32;
# взять модуль CRC32 можно
# http://search.cpan.org/CPAN/authors/id/S/SO/SOENKE/String-CRC32-1.4.tar.gz
# или по поиску в гугле или на cpan.org
use IO::Socket;
my $errors;
BEGIN {
$SIG{__DIE__} = sub {
my $text = shift;
print "ERROR: $text\n";
exit(0);
};
}
sub dec2hex {my $decnum = $_[0];
my $hexnum="";
my $tempval="";
while ($decnum != 0) {$tempval = $decnum % 16;
if ($tempval > 9) {$tempval = chr($tempval + 55);}
$hexnum = $tempval . $hexnum;
$decnum = int($decnum / 16);
if ($decnum < 16) {if ($decnum > 9) {$decnum = chr($decnum + 55);}
$hexnum = $decnum . $hexnum; $decnum = 0}}
return $hexnum;
}
# перевод DEC -> HEX
sub GetFileD
{
# Получение файла по HTTP
my $name;
$name=$_[0];
$document=$fold.$name;
$/ = undef;
$iop = IO::Socket::INET->new(Timeout=>20, Proto => "tcp", PeerAddr => $host[$idd], PeerPort => $port) or $errors="1";
if ($! eq "Invalid argument") {$errors="1";return("")}
# еще один бубен
unless ($iop)
{
$errors="1";
return("");
}
$errors="0";
$iop->autoflush(1);
$/ = undef;
# 2 бубенчика
$iop->print ("GET $document HTTP/1.0\nAccept: */*\nUser-Agent: DrWebUpdate-6.00.0.03030 (windows: 5.01.2600)\nProxy-Connection: Keep-Alive\n
X-DrWeb-Validate: 00000000000000000000000000000000\n
X-DrWeb-KeyNumber: 0000000000\n
Pragma: no-cache\nHost: $host[$idd]\n\n") or $errors="1";
### 4 строки выше собрать в одну, заменив параметры X-DrWeb-Validate и
### X-DrWeb-KeyNumber которые можно получить из штатной утилиты обновления,
### запустив ее вот так
### "C:\Program Files\DrWeb\DrWebUpW.exe" /GO /RP!UpdateLog.txt /dbg /dbg /dbg
### и найти данные параметры в файле !UpdateLog.txt
### если строки не собрать - скрипт работать НЕ БУДЕТ! ошибок кстати не выдаст :-)
$a = <$iop>;
close $iop;
if ($a) {if ($a eq "") {$errors="1";$a="Error!\n\n"}} else {$errors="1";$a="!Error!\n\n"}
($head,$body) = split /\r?\n\r?\n/,$a,2;
$head="";
if ($body) {if ($body eq "") {$errors="1";$body=""}} else {$errors="1";$body=""}
return($body);
}
@disabled=("timestamp","update.drl");
($sec,$min,$hour,$mday,$mon,$year,$sec,$sec,$sec)=localtime;
$sec++;
$mon++;
$year=$year+"1900";
if ($mday<"10") {$mday="0".$mday}
if ($mon<"10") {$mon="0".$mon}
if ($hour<"10") {$hour="0".$hour}
if ($min<"10") {$min="0".$min}
$nowtime="$mday/$mon/$year $hour:$min";
$namesds="$mday-$hour-$min";
# тут получаем локальное время, дату и формируем переменные для времени
$host[1]= 'update.msk.drweb.com';
$host[2]= 'update.msk3.drweb.com';
$host[3]= 'update.drweb.com';
$host[4]= 'update.fr1.drweb.com';
$host[5]= 'update.msk5.drweb.com';
$host[6]= 'update.msk6.drweb.com';
$host[7]= 'update.msk7.drweb.com';
$host[8]= 'update.us.drweb.com';
# Адреса серверов обновления
$idd="1";
# Не менять!
$maxidd="8";
# Максимально серверов в списке
$port = '80';
# удаленный порт
#$fold = '/500/sspace/windows/';
$fold = '/x86/600/sspace/windows/';
# папка на серверах, откуда берутся обновления - с начальным и конечным слешами
$paths="/var/basef6ss/";
# локальный путь к базам
$paths1="/var/base/";
# локальный путь к файлу drweb32.lst
$logff="/var/drwebf6ss.log";
#$logff="/dev/tty";
# лог-файл. или укажите для вывода на экран в качестве имени /dev/tty
open (LogF,">>$logff") or die "$nowtime: can not append log file $logff";
# открыть лог
$name = "drweb32.lst";
# не менять!
#$nameA = "drweb32.lst";
$nameA = "drweb32f6ss._lst";
# имя файла drweb32.lst - для выборочной раздачи может меняться
$nameorg=$paths1.$nameA."_org";
# имя оригинального файла, принятого с сервера (оригинальная копия)
$errors='0';$idd="1";$okkey="0";while (($okkey < "1")&&($idd <= $maxidd))
{ $body=GetFileD('drweb32.lst');
if ($errors ne "1") {$errors="0";$okkey="1";} else {$idd++;$errors="0"}
}
if ($errors eq '1') {print LogF "$nowtime: LST Can not connect to http demon on $host[$idd]=$idd at port $port: $!\n";exit;}
$error="0";open (Forg,">$nameorg") or $error="1";if ($error eq "1") {print LogF "$nowtime: can not write file $nameorg";$error="0"}
print Forg $body;
close (Forg);
$names=$paths.$name; #lst
$namesd=$paths1.$nameA; #не менять!
$namesds=$paths1."old/".$nameA.$namesds;
$body=~ s/\x0A/|/g;
$body=~ s/\x0D//g;
@data=split(/\|/,$body);
$namess=$names."-"; #не менять!
$errorcrc="0";
#print @data;
$error="0";open (F,">$namess") or $error="1";
if ($error eq "1") {print LogF "$nowtime: Can not write file $namess";$error="0"}
for ($iz=0; $iz<=$#data; $iz++)
{$datas=$data[$iz];
$loc = rindex($datas, "<");if ($loc >0) {$datas =~ s/>/\\/g;$datas =~ s/</\\/g;}
$loc = rindex($datas, chr(92));
if ($loc>0) {$datas=substr($datas,0,1).substr($datas,$loc+1,length($datas))}
#if (index($datas,'[') < 1) {
if ((substr($datas,0,1) ne "[")&&(index($datas,"timestamp") < 1)) {
@ob=split(/\,/,$datas);$ob[0]=substr($ob[0],1,length($ob[0]));$names=$paths.$ob[0];$error="0";$crc="0";
if (substr($datas,0,1) eq "-") {foreach $filename (glob($names)) {unlink("$filename");}}
# удалить файл с -
else
{$dw="dws".chr(92);
if (index($datas,$dw,0) >0) {$ob[0]="dws".chr(92).$ob[0];}
open (F1,"<$names") or $error="1";
if ($error eq "0") {$crc = crc32(*F1); # для внутренней функции
}
close(F1);$obs=substr($ob[1],1,length($ob[1]));$obs=~ tr/A-Zю-ъ/a-zЮ-Ъ/;
$crcs=dec2hex($crc);
#print ":$crcs:$obs:$ob[1]:$ob[2]\n";
$obs=hex ($obs);$crcold=$crc;
if ($crc ne $obs) {$error="1";}
if ($error eq "1") # начать загрузку файла - не совпадает CRC32
{$errors='0';$idd="1";$okkey="0";
while (($okkey < "1")&&($idd <= $maxidd))
{
$ffile="";
$ffile=GetFileD($ob[0]);if ($ffile eq "") {$errors="1"}
#print $ob[0].":".$ffile."\n";
if ($errors ne "1") {$errors="0";$okkey="1";print LogF "$nowtime: $ob[0]: ";} else {$idd++;}
}
if ($errors eq "1") {print LogF "$nowtime: $ob[0] Can not connect to http demon on $host[$idd]=$idd at port $port: $!\n";
# если файл кривой - обнуляем
#print $ob[0]."\n";
$errors="0";$okkey="1";$ffile="";
#exit;
}
$namesu=$names."~new";
$error="0";open (F1,">$namesu") or $error="1";if ($error eq "1") {print LogF "$nowtime: Can not create file $namesu";$error="0"} # error
print F1 $ffile;close(F1);print LogF "From: $idd\n";
$crc1="0";$error="0";open (F1,"<$namesu") or $error="1";if ($error eq "0") {$crc1 = crc32(*F1);close(F1);}
if ($crc1) {} else {$crc1="0"}
if (($crc1 eq $obs)||($crc1 eq "0")) { unlink($names);rename($namesu,$names);
open (F1,"<$names") or $error="1";
if ($error eq "0") {$crc2 = crc32(*F1);close(F1);
if ($crc2 ne $crc1) {print LogF "$nowtime: CRC: dataflush $ob[0]=$crc2; list=$obs; crc1=$crc1\n";
$data[$iz]="";}
}
}
else { # error CRC in new file
$obzzz=dec2hex($crcold);
# $data[$iz]="$ob[0], $obzzz";
$data[$iz]="";
$acrc1=dec2hex($crc1);
$acrc2=dec2hex($obs);
print LogF "$nowtime: CRC: erasenew $ob[0]=$acrc1; list=$acrc2; Write: $obzzz\n";
unlink($namesu);
$errorcrc="1";
}
}
}
# end of VDB
}
if (($data[$iz] ne "")&&(index($data[$iz],"update.drl") eq -1)
&&(index($data[$iz],"timestamp") eq -1)
) {print F "$data[$iz]\n";}
}
close (F);
($d,$d,$d,$d,$d,$d,$d,$size,$d,$d,$d,$d,$d) = stat($namess);$d="";
if ($size ne "0")
# если бубен сработал - не обновлять LST
{
$crc1="0";$crc2="0";
open (F1,"<$namesd") or $error="1";if ($error eq "0") {$crc1 = crc32(*F1);close(F1);}
open (F1,"<$namess") or $error="1";if ($error eq "0") {$crc2 = crc32(*F1);close(F1);}
# if ($crc1 ne $crc2)
# если новый и старый LST файлы разные
{
# $error="0";rename ($namesd,$namesds) or $error="1";if ($error eq "1") {print LogF "error rename old file"}
$error="0";rename ($namess,$namesd) or $error="1";if ($error eq "1") {print LogF "error rename new file"}
}
# else {unlink($namess);}
}
#chmod 384,$namesd;
close (LogF);
P.S. согласен, скрипт кривоват, но работает в принципе нормально. в случа сбоев автоматом переключается на следующие зеркала.
недостаток - drweb32.lst все же получает с первого доступного - могут быть разногласия, но переделывать лень.