development

Мониторинг серверов teeworlds

Скрипт для опроса статуса серверов игры teeworlds версии 0.6. Поочередно подключается к серверам и собирает данные, которые затем выводит во внешний файл. Собранная информация затем может использоваться для построения web-страницы (пример)

Скрипт написан на языке perl с использованием стандартных модулей, поэтому может выполняться на любой системе семейства linux и других, поддерживающих интерпретатор perl. Доступен к использованию под открытой лицензией GNU GPLv2

Модули, использованные при разработке

Возможности

Получаемые данные

Использование

Для запуска скрипта необходимо установить на него право на исполнение (chmod +x sv_stat_get.pl) и запустить его в консоли (./sv_stat_get.pl). Скрипт поочередно пройдёт по перечисленным серверам игры и после выполнения сохранит полученную информацию в файл info в формате хеша perl. Для дальнейшей обработки информация доступна для другого скрипта с использованием функции info_restore. Для автомацизации процесса необходимо добавить скрипт в планировщик задач cron

Настройки

Список отслеживаемых серверов задаётся в конце скрипта, после строки __DATA__. Список должен быть в формате "ip_адрес порт"

Скачать

Скачать скрипт мониторинга можно по этой ссылке

Вы также можете запустить скачать и запустить программу просто выполнив в консоли следующую команду:

wget http://disarmer.ru/dev/devel/_server_monitoring/sv_stat_get.pl.gz&&gzip -df sv_stat_get.pl.gz&&perl sv_stat_get.pl

Исходный код

#!/usr/bin/perl -w
use strict;
use Data::Dumper;
use IO::Socket::INET;
my (%serv,%flags,@servers);#объявляем переменные
$_=<DATA>;
chomp;
for(split /[;\ ]+/){
	@_=split ',';
	$flags{$_[1]}=$_[0];#строим таблицу соответсвия флагов и кодов
}
for(<DATA>){
	chomp;
	push @servers,[split ' '];#получаем список серверов для мониторинга
}
for(@servers){
	@_=@{$_};
	my ($name,$ref)=&get_tw_server;#опрашиваем сервера
	unless($name){
		warn "не удалось подключиться к серверу ",join(':',@_);
		next;
	}
	$serv{$name}=$ref;#сохраняем данные в хэше
}
&info_dump(\%serv);#экспортируем статус всех серверов в файл

sub info_restore{
	open FH,'<info';
	$_=join '', <FH>;	
	close FH;
	my $ref=eval $_;
	return $ref;
}
sub info_dump{
	$_=shift;
	%_=%{$_};
	local $Data::Dumper::Terse =1;
	local $Data::Dumper::Indent=1;
	$_{'gen_time'}=time();
	open FH,'>info';
	print FH Dumper(\%_);
	close FH;	
}
sub get_tw_server{
	my ($host,$port)=@_;
	my %res;
	print "connect $host:$port\n";
	my $sock = new IO::Socket::INET(
		'PeerAddr' => $host,
		'PeerPort' => $port,
		'Proto'    => 'udp',
		'TimeOut'  => 5);#создаем соединение
	die "Could not create socket: $!\n" unless $sock;
	my $timeo = pack("ll", 5, 0); #qq for 64 bit systems (!?)
	$sock->sockopt(SO_RCVTIMEO, $timeo);
	my $data ="\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x67\x69\x65\x33\x05";#отправляем пакет с запросом
	syswrite $sock, $data;	
	undef $_;
	sysread($sock, $_, 65535);
	if($_){
		my @info=split "\x00",$_;
		my ($ver,$name,$map,$type)=@info[1..4];
		my @players;
		for (my $i=0;$i<=$info[8]*5-5;$i+=5){#wtf!?
			@_=@info[$i+10..$i+14];
			$_[2]=$flags{$_[2]};
			push @players,[@_];
		}
		($res{'ver'},$res{'map'},$res{'host'},$res{'port'})=($ver,$map,$host,$port);
		($res{'plr_act'},undef,$res{'plr_all'},$res{'plr_max'},$res{'plr_spect'})=(@info[6..9],$info[8]-$info[6]);
		$res{'players'}=\@players;
		close $sock;
		return ($name,\%res);
	}else {return}
	close $sock;#закрываем соединение
}
__END__
default,-1; XEN,901; XNI,902; XSC,903; XWA,904; SS,737; AF,4; AX,248; AL,8; DZ,12; AS,16; AD,20; AO,24; AI,660; AG,28; AR,32; AM,51; AW,533; AU,36; AT,40; AZ,31; BS,44; BH,48; BD,50; BB,52; BY,112; BE,56; BZ,84; BJ,204; BM,60; BT,64; BO,68; BA,70; BW,72; BR,76; IO,86; BN,96; BG,100; BF,854; BI,108; KH,116; CM,120; CA,124; CV,132; KY,136; CF,140; TD,148; CL,152; CN,156; CX,162; CC,166; CO,170; KM,174; CG,178; CD,180; CK,184; CR,188; CI,384; HR,191; CU,192; CW,531; CY,196; CZ,203; DK,208; DJ,262; DM,212; DO,214; EC,218; EG,818; SV,222; GQ,226; ER,232; EE,233; ET,231; FK,238; FO,234; FJ,242; FI,246; FR,250; GF,254; PF,258; TF,260; GA,266; GM,270; GE,268; DE,276; GH,288; GI,292; GR,300; GL,304; GD,308; GP,312; GU,316; GT,320; GG,831; GN,324; GW,624; GY,328; HT,332; VA,336; HN,340; HK,344; HU,348; IS,352; IN,356; ID,360; IR,364; IQ,368; IE,372; IM,833; IL,376; IT,380; JM,388; JP,392; JE,832; JO,400; KZ,398; KE,404; KI,296; KP,408; KR,410; KW,414; KG,417; LA,418; LV,428; LB,422; LS,426; LR,430; LY,434; LI,438; LT,440; LU,442; MO,446; MK,807; MG,450; MW,454; MY,458; MV,462; ML,466; MT,470; MH,584; MQ,474; MR,478; MU,480; MX,484; FM,583; MD,498; MC,492; MN,496; ME,499; MS,500; MA,504; MZ,508; MM,104; NA,516; NR,520; NP,524; NL,528; NC,540; NZ,554; NI,558; NE,562; NG,566; NU,570; NF,574; MP,580; NO,578; OM,512; PK,586; PW,585; PA,591; PG,598; PY,600; PE,604; PH,608; PN,612; PL,616; PT,620; PR,630; QA,634; RE,638; RO,642; RU,643; RW,646; BL,652; SH,654; KN,659; LC,662; MF,663; PM,666; VC,670; WS,882; SM,674; ST,678; SA,682; SN,686; RS,688; SC,690; SL,694; SG,702; SX,534; SK,703; SI,705; SB,90; SO,706; ZA,710; GS,239; ES,724; LK,144; SD,736; SR,740; SZ,748; SE,752; CH,756; SY,760; TW,158; TJ,762; TZ,834; TH,764; TL,626; TG,768; TK,772; TO,776; TT,780; TN,788; TR,792; TM,795; TC,796; TV,798; UG,800; UA,804; AE,784; GB,826; US,840; UY,858; UZ,860; VU,548; VE,862; VN,704; VG,92; VI,850; WF,876; EH,732; YE,887; ZM,894; ZW,716
127.0.0.1 8300
127.0.0.1 8303
127.0.0.1 8304
127.0.0.1 8305
127.0.0.1 8306
127.0.0.1 8310
127.0.0.1 8311