lilalo

changeset 27:098664cf339c v_0_2_4

Выполнены шаги 4,5 в плане N05 по построению распределённой системы lilalo.
Шаг <6> в настоящее время не является необходимым.


Введено понятие сеанса.
Сеансом считается процедура работы с системой, начинающаяся с регистрации
в ней и зазаканчивающаяся разрегистрацией, и сопровождающаяся ведением одного
файла скрипта.
Одновременно с созданием скрипта (.script) создаётся соответствующий ему
файл с информацией о сеансе (.info).
Каждый сеанс имеет уникальный в пределах хоста идентификатор,
~local_session_id~, который впоследствии позволяет определить,
какие команды относятся к какому сеансу.

Добавлен backend-сервер, который получает данные от агентов и записывает
из в backend (в настойщий момент - в XML-файл).
Данные передаются по tcp-соединениям.
(Одновременно может работать несколько серверов.
Блокировка файла при записи пока что не выполняется ОСТОРОЖНО!!!!!!)

Агент периодически пытается отправить backend-серверу содержимое своего кэш-файла,
и если ему это удаётся, кэш файл очищается -- данные теперь хранятся в backend'е.

Взаимодействие агентов, backend-сервера и frontend'а
сейчас выполнеятся так:


+-------+
| |
| cache |
| |
+-^---+-+
| |
. ^ v . ^^ . +---------+ . ^^ .
/ \ tcp / \ | | / \ CGI
( agent )----->( backend- )-->| backend |-->( frontend )----->
\ / \ сервер / | | \ /
' . ' ' .. ' +---------+ ' .. '
^
|
+----+----+
| |
|*.script |
| *.info |
| |
+---------+

l3-frontend:
Теперь может выдавать результат работы на стандартный поток вывода.
Вместо имени файла нужно указать символ -

Добавлены файлы:

l3-backend - backend-сервер
l3-cgi - CGI-обвязка для l3-frontend'а

Новые конфигурационные параметры:
frontend_css Путь к файлу CSS, используемому в HTML-странице, которую генерирует frontend
frontend_google_ico Путь к иконке google
frontend_linux_ico Путь к иконке linux
frontend_freebsd_ico Путь к иконке freebsd
frontend_opennet_ico Путь к иконке opennet
frontend_local_ico Путь к иконке локальной документации

backend_address IP-адрес интерфейса, на котором работает backend-сервер
backend_port Порт, который слушает backend-сервер
backend_pidfile Путь к файлу, который хранит идентификатор процесса backend-сервера
backend_datafile Путь к файлу хранилищу (файлу backend)
author devi
date Mon Nov 07 11:24:49 2005 +0200 (2005-11-07)
parents 916661a89335
children 450b6ac9b657
files l3-agent l3-backend l3-cgi l3-frontend l3config.pm lm-install
line diff
     1.1 --- a/l3-agent	Thu Nov 03 17:53:03 2005 +0200
     1.2 +++ b/l3-agent	Mon Nov 07 11:24:49 2005 +0200
     1.3 @@ -10,6 +10,7 @@
     1.4  use Text::Iconv;
     1.5  use Data::Dumper;
     1.6  use Time::Local 'timelocal_nocheck';
     1.7 +use IO::Socket;
     1.8  
     1.9  use lib ".";
    1.10  use l3config;
    1.11 @@ -18,6 +19,7 @@
    1.12  our @Command_Lines;
    1.13  our @Command_Lines_Index;
    1.14  our @Diffs;
    1.15 +our %Sessions;
    1.16  
    1.17  our %Commands_Stat;		# Statistics about commands usage
    1.18  our %Files_Stat;		# Statistics about commands usage
    1.19 @@ -44,7 +46,7 @@
    1.20  
    1.21  sub save_cache_stat;
    1.22  sub load_cache_stat;
    1.23 -
    1.24 +sub print_session;
    1.25  
    1.26  sub load_diff_files
    1.27  {
    1.28 @@ -224,22 +226,50 @@
    1.29  		
    1.30  	print "Loading lm-scripts...\n" if $Config{"verbose"} =~ /y/;
    1.31  
    1.32 -	my @lab_scripts = <$lab_scripts_path/$lab_scripts_mask>;
    1.33  	my $file;
    1.34 -	my $files_number = $#lab_scripts;
    1.35 -	my $ii = 0;
    1.36  	my $skip_info;
    1.37  
    1.38  	my $commandlines_loaded =0;
    1.39  	my $commandlines_processed =0;
    1.40  
    1.41 +	my @lab_scripts = <$lab_scripts_path/$lab_scripts_mask>;
    1.42  	for $file (@lab_scripts){
    1.43 -		#printf "\t%i %3.2f\n", $ii, (100*$ii++/$files_number) if $Config{"verbose"} =~ /y/;
    1.44  		
    1.45  		# Пропускаем файл, если он не изменялся со времени нашего предудущего прохода
    1.46  		my $size = (stat($file))[7];
    1.47  		next if ($Script_Files{$file} && $Script_Files{$file}->{size} && $Script_Files{$file}->{size} >= $size);
    1.48  
    1.49 +
    1.50 +		my $local_session_id;
    1.51 +		# Начальное значение идентификатора текущего сеанса определяем из имени скрипта
    1.52 +		# Впоследствии оно может быть уточнено
    1.53 +		$file =~ /.*\/(.*)\.script$/;
    1.54 +		$local_session_id = $1;
    1.55 +
    1.56 +		#Если файл только что появился, 
    1.57 +		#пытаемся найти и загрузить информацию о соответствующей ему сессии
    1.58 +		if (!$Script_Files{$file}) {
    1.59 +			my $session_file = $file;
    1.60 +			$session_file =~ s/\.script/.info/;
    1.61 +			if (open(SESSION, $session_file)) {
    1.62 +				local $/;
    1.63 +				my $data = <SESSION>;
    1.64 +				close(SESSION);
    1.65 +
    1.66 +				for my $session_data ($data =~ m@<session>(.*?)</session>@sg) {
    1.67 +					my %session;
    1.68 +					while ($session_data =~ m@<([^>]*?)>(.*?)</\1>@sg) {
    1.69 +						$session{$1} = $2;
    1.70 +					}
    1.71 +					$local_session_id = $session{"local_session_id"} if $session{"local_session_id"};
    1.72 +					$Sessions{$session_id}=\%session;
    1.73 +				}
    1.74 +
    1.75 +				#Загруженную информацию сразу же отправляем в поток
    1.76 +				print_session($Config{cache}, $local_session_id);
    1.77 +			}
    1.78 +		}
    1.79 +		
    1.80  		open (FILE, "$file");
    1.81  		binmode FILE;
    1.82  		
    1.83 @@ -278,7 +308,8 @@
    1.84  
    1.85  =cut 
    1.86  
    1.87 -ТАБЛИЦА КОМАНД
    1.88 +Атрибуты cline
    1.89 +Список полей, характеризующих командную строку
    1.90  
    1.91  	uid
    1.92  		Идентификатор пользователя
    1.93 @@ -338,6 +369,7 @@
    1.94  		Текстовый комментарий к команде.
    1.95  		Может генерироваться из самого лога с помощью команд
    1.96  			#^ Комментарий  
    1.97 +			#= Комментарий
    1.98  			#v Комментарий
    1.99  		в том случае, если для комментирования достаточно одной строки,
   1.100  		или с помощью команд
   1.101 @@ -348,9 +380,11 @@
   1.102  		В последнем случае комментарий может содержать 
   1.103  		заголовок, абзацы и несложное форматирование.
   1.104  
   1.105 -		Символ ^ или v после знака комментария # обозначает,
   1.106 +		Символы ^, v или = после знака комментария # обозначает,
   1.107  		к какой команде относится комментарий:
   1.108 -		к предыдущей (^) или последующей (v)
   1.109 +		к предыдущей (^), последующей (v)
   1.110 +		или это общий комментарий по тексту, не относящийся непосредственно
   1.111 +		ни к одной из них (=)
   1.112  
   1.113  	err 
   1.114  		Код завершения командной строки
   1.115 @@ -397,22 +431,22 @@
   1.116  		
   1.117  		1 - версия использующаяся в lilalo
   1.118  		
   1.119 -	raw_file (*)
   1.120 +	raw_file
   1.121  		Имя файла, в котором находится бинарное представление журнала.
   1.122  		Может содержать ключевое слово HERE, 
   1.123  		обозначающее что бинарное представление хранится
   1.124  		непосредственно в базе данных в атрибуте raw_data
   1.125  
   1.126 -	raw_start (*)
   1.127 +	raw_start
   1.128  		Начало блока командной строки в файле бинарного представления
   1.129  	
   1.130 -	raw_output_start (*)
   1.131 +	raw_output_start
   1.132  		Начало блока вывода
   1.133  	
   1.134 -	raw_end (*)
   1.135 +	raw_end
   1.136  		Конец блока командной строки в файле бинарного представления
   1.137  
   1.138 -	raw_cline (*)
   1.139 +	raw_cline
   1.140  		Необработанная командная строка (без приглашения) в бинарном виде
   1.141  	
   1.142  	raw_data (*)
   1.143 @@ -425,11 +459,12 @@
   1.144  	
   1.145  	Информация о сеансах
   1.146  
   1.147 -
   1.148 +		(см. lm-install)
   1.149  
   1.150  
   1.151  =cut
   1.152  
   1.153 +				$cl{"local_session_id"} = $local_session_id;
   1.154  				# Parse new command 
   1.155  				$cl{"uid"} = $3;
   1.156  				$cl{"euid"} = $cl{"uid"};	# Если в команде обнаружится sudo, euid поменяем на 0
   1.157 @@ -751,6 +786,7 @@
   1.158  
   1.159  		# Начинаем вывод команды
   1.160  		print OUT "<command>\n";
   1.161 +		print OUT "<local_session_id>",$cl->{session_id},"</local_session_id>\n";
   1.162  		print OUT "<time>",$cl->{time},"</time>\n";
   1.163  		print OUT "<raw_start>",$cl->{raw_start},"</raw_start>\n";
   1.164  		print OUT "<raw_output_start>",$cl->{raw_output_start},"</raw_output_start>\n";
   1.165 @@ -789,7 +825,54 @@
   1.166  
   1.167  	#print OUT "</livelablog>\n";
   1.168  	close(OUT);
   1.169 -	save_cache_stat();
   1.170 +}
   1.171 +
   1.172 +sub print_session
   1.173 +{
   1.174 +	my $output_filename = $_[0];
   1.175 +	my $local_session_id = $_[1];
   1.176 +	return if not defined($Sessions{$local_session_id});
   1.177 +
   1.178 +	open(OUT, ">>", $output_filename)
   1.179 +		or die "Can't open $output_filename for writing\n";
   1.180 +	print OUT "<session>\n";
   1.181 +	my %session = %{$Sessions{$local_session_id}};
   1.182 +	for my $key (keys %session) {
   1.183 +		print OUT "<$key>".$session{$key}."</$key>\n"
   1.184 +	}
   1.185 +	print OUT "</session>\n";
   1.186 +	close(OUT);
   1.187 +}
   1.188 +
   1.189 +sub send_cache
   1.190 +{
   1.191 +	`logger "step 0"`;
   1.192 +	`logger "step 1"`;
   1.193 +
   1.194 +	# Если в кэше что-то накопилось, 
   1.195 +	# попытаемся отправить это на сервер
   1.196 +	#
   1.197 +	my $cache_was_sent=0;
   1.198 +	
   1.199 +	if (open(CACHE, $Config{cache})) {
   1.200 +		local $/;
   1.201 +		my $cache = <CACHE>;
   1.202 +		close(CACHE);
   1.203 +
   1.204 +		my $socket = IO::Socket::INET->new(
   1.205 +							PeerAddr => $Config{backend_address},
   1.206 +							PeerPort => $Config{backend_port},
   1.207 +							proto	=> "tcp",
   1.208 +							Type 	=> SOCK_STREAM
   1.209 +						);
   1.210 +
   1.211 +		if ($socket) {
   1.212 +			print $socket $cache;
   1.213 +			close($socket);
   1.214 +			$cache_was_sent = 1;
   1.215 +		}
   1.216 +	}
   1.217 +	return $cache_was_sent;
   1.218  }
   1.219  
   1.220  sub save_cache_stat
   1.221 @@ -805,6 +888,7 @@
   1.222  {
   1.223  	if (open (CACHE, "$Config{cache_stat}")) {
   1.224  		while(<CACHE>) {
   1.225 +			chomp;
   1.226  			my ($f, $size, $tell) = split /\t/;
   1.227  			$Script_Files{$f}->{size} = $size;
   1.228  			$Script_Files{$f}->{tell} = $tell;
   1.229 @@ -813,65 +897,6 @@
   1.230  	};
   1.231  }
   1.232  
   1.233 -=cut
   1.234 -sub print_command_lines2
   1.235 -{
   1.236 -	my $output_filename=$_[0];
   1.237 -	open(OUT, ">", $output_filename)
   1.238 -		or die "Can't open $output_filename for writing\n";
   1.239 -
   1.240 -
   1.241 -	print OUT <<OUT;
   1.242 -<log>
   1.243 -OUT
   1.244 -
   1.245 -	my $cl;
   1.246 -	for my $i (@Command_Lines_Index) {
   1.247 -
   1.248 -		
   1.249 -		$cl = $Command_Lines[$i];
   1.250 -
   1.251 -
   1.252 -# Printing out
   1.253 -		print OUT <<OUT;
   1.254 -	<command>
   1.255 -		<day>$cl->{day}</day>
   1.256 -		<hour>$cl->{hour}</hour>
   1.257 -		<min>$cl->{min}</min>
   1.258 -		<sec>$cl->{sec}</sec>
   1.259 -		<tty>$cl->{tty}</tty>
   1.260 -		<uid>$cl->{uid}</uid>
   1.261 -		<euid>$cl->{euid}</euid>
   1.262 -		<prompt>$cl->{prompt}</prompt>
   1.263 -		<cline>$cl->{cline}</cline>
   1.264 -		<status>$cl->{err}</cline>
   1.265 -		<output>
   1.266 -$cl->{output}</output>
   1.267 -	</command>
   1.268 -OUT
   1.269 -	}
   1.270 -
   1.271 -	for my $diff (@Diffs) {
   1.272 -
   1.273 -		print OUT <<OUT;
   1.274 -	<diff>
   1.275 -		<path>$diff->{path}</path>
   1.276 -		<uid>$diff->{uid}</uid>
   1.277 -		<day>$diff->{day}</day>
   1.278 -		<hour>$diff->{hour}</hour>
   1.279 -		<min>$diff->{min}</min>
   1.280 -		<sec>$diff->{sec}</sec>
   1.281 -		<text>
   1.282 -$diff->{text}</text>
   1.283 -	</diff>
   1.284 -OUT
   1.285 -	}
   1.286 -
   1.287 -	print OUT <<OUT;
   1.288 -</log>
   1.289 -OUT
   1.290 -}
   1.291 -=cut
   1.292  
   1.293  main();
   1.294  
   1.295 @@ -882,73 +907,85 @@
   1.296  
   1.297  sub main
   1.298  {
   1.299 -$| = 1;
   1.300  
   1.301 -init_variables();
   1.302 -init_config();
   1.303 +	$| = 1;
   1.304  
   1.305 -for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) {
   1.306 -	load_diff_files($lab_log);
   1.307 -}
   1.308 +	init_variables();
   1.309 +	init_config();
   1.310  
   1.311 -if ($Config{"mode"} ne "daemon") {
   1.312 -	load_command_lines($Config{"input"}, $Config{"input_mask"});
   1.313 -	sort_command_lines;
   1.314 -	process_command_lines;
   1.315 -	print_command_lines($Config{"cache"});
   1.316 -} 
   1.317 -else {
   1.318 -	if (open(PIDFILE, $Config{agent_pidfile})) {
   1.319 -		my $pid = <PIDFILE>;
   1.320 -		close(PIDFILE);
   1.321 -		if ( ! -e "/proc/$pid" || !`grep $Config{"l3-agent"} /proc/$pid/cmdline && grep "uid:.*\b$<\b" /proc/$pid/status`) {
   1.322 -			print "Removing stale pidfile\n";
   1.323 -			unlink $Config{agent_pidfile};
   1.324 -				or die "Can't remove stale pidfile ". $Config{agent_pidfile}. " : $!";
   1.325 +	for my $lab_log (split (/\s+/, $Config{"diffs"} || $Config{"input"})) {
   1.326 +		load_diff_files($lab_log);
   1.327 +	}
   1.328 +
   1.329 +	if ($Config{"mode"} ne "daemon") {
   1.330 +
   1.331 +=cut
   1.332 +	В нормальном режиме работы нужно
   1.333 +	считать скрипты, обработать их и записать
   1.334 +	результат выполнения в результриующий файл.
   1.335 +	После этого завершить работу.
   1.336 +=cut
   1.337 +		load_command_lines($Config{"input"}, $Config{"input_mask"});
   1.338 +		sort_command_lines;
   1.339 +		process_command_lines;
   1.340 +		print_command_lines($Config{"cache"});
   1.341 +	} 
   1.342 +	else {
   1.343 +		if (open(PIDFILE, $Config{agent_pidfile})) {
   1.344 +			my $pid = <PIDFILE>;
   1.345 +			close(PIDFILE);
   1.346 +			if ( ! -e "/proc/$pid" || !`grep $Config{"l3-agent"} /proc/$pid/cmdline && grep "uid:.*\b$<\b" /proc/$pid/status`) {
   1.347 +				print "Removing stale pidfile\n";
   1.348 +				unlink $Config{agent_pidfile}
   1.349 +					or die "Can't remove stale pidfile ". $Config{agent_pidfile}. " : $!";
   1.350 +			}
   1.351 +			else {
   1.352 +				print "l3-agent is already running\n";
   1.353 +				exit(0);
   1.354 +			}
   1.355  		}
   1.356 -		else {
   1.357 -			print "l3-agent is already running\n";
   1.358 -			exit(0);
   1.359 +		if ($Config{detach} =~ /^y/i) {
   1.360 +			#$Config{verbose} = "no";
   1.361 +			my $pid = fork;
   1.362 +			exit if $pid;
   1.363 +			die "Couldn't fork: $!" unless defined ($pid);
   1.364 +
   1.365 +			open(PIDFILE, ">", $Config{agent_pidfile})
   1.366 +				or die "Can't open pidfile ". $Config{agent_pidfile}. " for wrting: $!";
   1.367 +			print PIDFILE $$;
   1.368 +			close(PIDFILE);
   1.369 +
   1.370 +			for my $handle (*STDIN, *STDOUT, *STDERR) {
   1.371 +				open ($handle, "+<", "/dev/null")
   1.372 +					or die "can't reopen $handle to /dev/null: $!"
   1.373 +			}
   1.374 +
   1.375 +			POSIX::setsid()
   1.376 +				or die "Can't start a new session: $!";
   1.377 +
   1.378 +			$0 = $Config{"l3-agent"};
   1.379 +			
   1.380 +			$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&process_was_killed;
   1.381  		}
   1.382 +		while (not $Killed) {
   1.383 +			@Command_Lines = ();
   1.384 +			@Command_Lines_Index = ();
   1.385 +			load_cache_stat();
   1.386 +			load_command_lines($Config{"input"}, $Config{"input_mask"});
   1.387 +			if (@Command_Lines) {
   1.388 +				sort_command_lines;
   1.389 +				process_command_lines;
   1.390 +				print_command_lines($Config{"cache"});
   1.391 +			}
   1.392 +			save_cache_stat();
   1.393 +			if (-e $Config{cache} && (stat($Config{cache}))[7]) {
   1.394 +				send_cache() && unlink($Config{cache});
   1.395 +			}
   1.396 +			sleep($Config{"daemon_sleep_interval"} || 1);
   1.397 +		}
   1.398 +		
   1.399 +		unlink $Config{agent_pidfile};
   1.400  	}
   1.401 -	if ($Config{detach} =~ /^y/i) {
   1.402 -		#$Config{verbose} = "no";
   1.403 -		my $pid = fork;
   1.404 -		exit if $pid;
   1.405 -		die "Couldn't fork: $!" unless defined ($pid);
   1.406 -
   1.407 -		open(PIDFILE, ">", $Config{agent_pidfile})
   1.408 -			or die "Can't open pidfile ". $Config{agent_pidfile}. " for wrting: $!";
   1.409 -		print PIDFILE $$;
   1.410 -		close(PIDFILE);
   1.411 -
   1.412 -		for my $handle (*STDIN, *STDOUT, *STDERR) {
   1.413 -			open ($handle, "+<", "/dev/null")
   1.414 -				or die "can't reopen $handle to /dev/null: $!"
   1.415 -		}
   1.416 -
   1.417 -		POSIX::setsid()
   1.418 -			or die "Can't start a new session: $!";
   1.419 -
   1.420 -		$0 = $Config{"l3-agent"};
   1.421 -		
   1.422 -		$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&process_was_killed;
   1.423 -	}
   1.424 -	while (not $Killed) {
   1.425 -		@Command_Lines = ();
   1.426 -		@Command_Lines_Index = ();
   1.427 -		load_cache_stat();
   1.428 -		load_command_lines($Config{"input"}, $Config{"input_mask"});
   1.429 -		if (@Command_Lines) {
   1.430 -			sort_command_lines;
   1.431 -			process_command_lines;
   1.432 -			print_command_lines($Config{"cache"});
   1.433 -		}
   1.434 -		sleep($Config{"daemon_sleep_interval"} || 1);
   1.435 -	}
   1.436 -	
   1.437 -	unlink $Config{agent_pidfile};
   1.438 -}
   1.439  
   1.440  }
   1.441  
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/l3-backend	Mon Nov 07 11:24:49 2005 +0200
     2.3 @@ -0,0 +1,106 @@
     2.4 +#!/usr/bin/perl
     2.5 +
     2.6 +use strict;
     2.7 +use lib '.';
     2.8 +use l3config;
     2.9 +use IO::Socket;
    2.10 +use POSIX qw(:sys_wait_h);
    2.11 +
    2.12 +sub main;
    2.13 +
    2.14 +main();
    2.15 +
    2.16 +sub REAPER {
    2.17 +	1 until (-1 == waitpid(-1, WNOHANG));
    2.18 +	$SIG{CHLD} = \&REAPER;
    2.19 +}
    2.20 +
    2.21 +sub process_was_killed
    2.22 +{
    2.23 +	# Здесь должна быть красивая процедура 
    2.24 +	# завершения демона
    2.25 +	unlink $Config{backend_pidfile};
    2.26 +	exit(0);
    2.27 +}
    2.28 +
    2.29 +sub main {
    2.30 +	init_config();
    2.31 +
    2.32 +
    2.33 +	# Проверяем, возможно демон уже запущен
    2.34 +	# Если он работает, просто завершаемся
    2.35 +	if (open(PIDFILE, $Config{backend_pidfile})) {
    2.36 +		my $pid = <PIDFILE>;
    2.37 +		close(PIDFILE);
    2.38 +		if ( ! -e "/proc/$pid" || !`grep $Config{"l3-backend"} /proc/$pid/cmdline && grep "uid:.*\b$<\b" /proc/$pid/status`) {
    2.39 +			print "Removing stale pidfile\n";
    2.40 +			unlink $Config{backend_pidfile}
    2.41 +				or die "Can't remove stale pidfile ". $Config{backend_pidfile}. " : $!";
    2.42 +		}
    2.43 +		else {
    2.44 +			print "l3-backend is already running\n";
    2.45 +			exit(0);
    2.46 +		}
    2.47 +	}
    2.48 +
    2.49 +	# Уходим в background, если необходимо
    2.50 +	if ($Config{detach} =~ /^y/i) {
    2.51 +		#$Config{verbose} = "no";
    2.52 +		my $pid = fork;
    2.53 +		exit if $pid;
    2.54 +		die "Couldn't fork: $!" unless defined ($pid);
    2.55 +
    2.56 +		open(PIDFILE, ">", $Config{backend_pidfile})
    2.57 +			or die "Can't open pidfile ". $Config{backend_pidfile}. " for wrting: $!";
    2.58 +		print PIDFILE $$;
    2.59 +		close(PIDFILE);
    2.60 +
    2.61 +		for my $handle (*STDIN, *STDOUT, *STDERR) {
    2.62 +			open ($handle, "+<", "/dev/null")
    2.63 +				or die "can't reopen $handle to /dev/null: $!"
    2.64 +		}
    2.65 +
    2.66 +		POSIX::setsid()
    2.67 +			or die "Can't start a new session: $!";
    2.68 +
    2.69 +		$0 = $Config{"l3-backend"};
    2.70 +		
    2.71 +		$SIG{INT} = $SIG{TERM} = $SIG{HUP} = \&process_was_killed;
    2.72 +	}
    2.73 +
    2.74 +	# Открываем сетевой сокет и слушаем
    2.75 +	my $server = IO::Socket::INET->new(
    2.76 +			LocalPort 	=> $Config{backend_port},
    2.77 +			Type		=> SOCK_STREAM,
    2.78 +			Reuse		=> 1,
    2.79 +			Listen		=> 10 );
    2.80 +	
    2.81 +	if (!$server) {
    2.82 +		die "Couldn't bind to socket ".$Config{backend_port}."\n";
    2.83 +	}
    2.84 +
    2.85 +	$SIG{CHLD} = 'IGNORE';
    2.86 +
    2.87 +	# При получении новых соединенений,
    2.88 +	# порождаем дочерние процессы
    2.89 +	while (my $client = $server->accept()) {
    2.90 +		my $pid;
    2.91 +		next if $pid = fork;
    2.92 +		die "fork: $!" unless defined $pid;
    2.93 +
    2.94 +		# Это наш ответвлённый клиент
    2.95 +		close($server);
    2.96 +
    2.97 +		# Считываем данные и передаём их в точку получения
    2.98 +		open(OUT, ">>", $Config{"backend_datafile"});
    2.99 +		select OUT; $|=1;
   2.100 +		while(<$client>) {
   2.101 +			print OUT $_;
   2.102 +		}
   2.103 +		close(OUT);
   2.104 +	} 
   2.105 +	continue {
   2.106 +		# Наш родитель
   2.107 +		close ($client);
   2.108 +	}
   2.109 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/l3-cgi	Mon Nov 07 11:24:49 2005 +0200
     3.3 @@ -0,0 +1,17 @@
     3.4 +#!/usr/bin/perl
     3.5 +
     3.6 +use strict;
     3.7 +use CGI qw(:standard);
     3.8 +
     3.9 +my $value = param('PARAM');
    3.10 +
    3.11 +print header(
    3.12 +		-charset => "utf-8", 
    3.13 +		);
    3.14 +chdir("/home/devi/cvs/lilalo");
    3.15 +open (FRONTEND, "./l3-frontend --output - |");
    3.16 +while (<FRONTEND>) {
    3.17 +	print;
    3.18 +}
    3.19 +close(FRONTEND);
    3.20 +
     4.1 --- a/l3-frontend	Thu Nov 03 17:53:03 2005 +0200
     4.2 +++ b/l3-frontend	Mon Nov 07 11:24:49 2005 +0200
     4.3 @@ -29,7 +29,7 @@
     4.4  	init_variables();
     4.5  	init_config();
     4.6  
     4.7 -	load_command_lines_from_xml($Config{"cache"});
     4.8 +	load_command_lines_from_xml($Config{"backend_datafile"});
     4.9  	print_command_lines($Config{"output"});
    4.10  }
    4.11  
    4.12 @@ -334,7 +334,7 @@
    4.13  	<html>
    4.14  	<head>
    4.15  	<meta content='text/html; charset=utf-8' http-equiv='Content-Type' />
    4.16 -	<link rel='stylesheet' href='labmaker.css' type='text/css'/>
    4.17 +	<link rel='stylesheet' href='$Config{frontend_css}' type='text/css'/>
    4.18  	</head>
    4.19  	<body>
    4.20  	<script>
    4.21 @@ -372,10 +372,15 @@
    4.22  
    4.23  	$Result{"header"} .= "</form></td></tr></table>\n";
    4.24  
    4.25 -	open(OUT, ">", $output_filename)
    4.26 -		or die "Can't open $output_filename for writing\n";
    4.27 -	print OUT $Result{"header"}, $Result{"body"}, $Result{"stat"}, $Result{"help"}, $Result{"about"}, $Result{"footer"};
    4.28 -	close(OUT);
    4.29 +	if ($output_filename eq "-") {
    4.30 +		print $Result{"header"}, $Result{"body"}, $Result{"stat"}, $Result{"help"}, $Result{"about"}, $Result{"footer"};
    4.31 +	}
    4.32 +	else {
    4.33 +		open(OUT, ">", $output_filename)
    4.34 +			or die "Can't open $output_filename for writing\n";
    4.35 +		print OUT $Result{"header"}, $Result{"body"}, $Result{"stat"}, $Result{"help"}, $Result{"about"}, $Result{"footer"};
    4.36 +		close(OUT);
    4.37 +	}
    4.38  }
    4.39  
    4.40  
     5.1 --- a/l3config.pm	Thu Nov 03 17:53:03 2005 +0200
     5.2 +++ b/l3config.pm	Mon Nov 07 11:24:49 2005 +0200
     5.3 @@ -46,6 +46,12 @@
     5.4  		#"output"			=>	"report.xml",
     5.5  		"output_mask"			=>	"INDEX",
     5.6  		"output_format"			=>	"html",
     5.7 +		"frontend_css"			=>	"/l3/l3.css",
     5.8 +		"frontend_google_ico"		=>	"/l3/google.ico",
     5.9 +		"frontend_linux_ico"		=>	"/l3/linux.ico",
    5.10 +		"frontend_freebsd_ico"		=>	"/l3/freebsd.ico",
    5.11 +		"frontend_opennet_ico"		=>	"/l3/opennet.ico",
    5.12 +		"frontend_local_ico"		=>	"/l3/freebsd.ico",
    5.13  
    5.14  		"signature"			=>	"#lm:",
    5.15  		"from"				=>	"",
    5.16 @@ -62,7 +68,13 @@
    5.17  		"detach"			=>	"yes",
    5.18  		"agent_pidfile"			=> 	"$ENV{HOME}/.labmaker/l3-agent.pid",
    5.19  
    5.20 +		"backend_address"		=>	"127.0.0.1",
    5.21 +		"backend_port"			=> 	"18030",
    5.22 +		"backend_pidfile"		=> 	"/tmp/l3-backend.pid",
    5.23 +		"backend_datafile"		=> 	"/tmp/backend.xml",
    5.24 +
    5.25  		"l3-agent"			=>	"l3-agent", 
    5.26 +		"l3-backend"			=>	"l3-backend", 
    5.27  		
    5.28  		"course-name" => "", 
    5.29  		"course-code" => "", 
     6.1 --- a/lm-install	Thu Nov 03 17:53:03 2005 +0200
     6.2 +++ b/lm-install	Mon Nov 07 11:24:49 2005 +0200
     6.3 @@ -68,31 +68,54 @@
     6.4  		| sed '/LabMaker:START/,/LabMaker:END/ d' \
     6.5  		> $temp_file
     6.6  	cat <<'LM_bash_profile' >> $temp_file
     6.7 -	# LabMaker:START
     6.8 -	TTY=`tty` 
     6.9 +# LabMaker:START
    6.10 +LMHOME=~/.labmaker
    6.11 +mkdir -p ${LMHOME}
    6.12  
    6.13 -	uname -a | grep -qi bsd && bsd=yes
    6.14 +uname -a | grep -qi bsd && bsd=yes
    6.15 +flush="-f"			#linux
    6.16 +[ -n "$bsd" ] && flush="-t 0"	#freebsd
    6.17  
    6.18 -	this_term=`w | grep "${TTY##/dev/}" | awk '{print $8;}'`
    6.19 -	# freeBSD: 
    6.20 -	[ -n "$bsd" ] && this_term=`w | grep "${TTY##/dev/tty}" | awk '{print $6;}'`
    6.21 +tty=`tty` 
    6.22 +this_term=`w | grep "${tty##/dev/}" | awk '{print $8;}'`
    6.23 +# freeBSD: 
    6.24 +[ -n "$bsd" ] && this_term=`w | grep "${tty##/dev/tty}" | awk '{print $6;}'`
    6.25  
    6.26  
    6.27 +export PS1='\[`	
    6.28 +	a="$?";
    6.29 +	HIDDEN=$([ "$a" = 0 ] || echo -n ^"$a")$(echo -n _${UID}_)$(echo -n _$$_)$(date\
    6.30 +		+"%j$(cat ${LMHOME}/lab 2>/dev/null) %H:%M:%S");
    6.31 +	echo $HIDDEN`\033[50D\033[K\][\u@\h:\W]\$ '
    6.32  
    6.33 -	LMHOME=~/.labmaker
    6.34 -	mkdir -p ${LMHOME}
    6.35 -	flush="-f"	#linux
    6.36 -	[ -n "$bsd" ] && flush="-t 0"	#freebsd
    6.37 -	export PS1='\[`	a="$?";
    6.38 -		HIDDEN=$([ "$a" = 0 ] || echo -n ^"$a")$(echo -n _${UID}_)$(echo -n _$$_)$(date\
    6.39 -			+"%j$(cat ~/.labmaker/lab 2>/dev/null) %H:%M:%S");
    6.40 -		echo $HIDDEN`\033[50D\033[K\][\u@\h:\W]\$ '
    6.41 +if [ -n "$this_term" ] && echo $this_term | grep -qv script
    6.42 +then	
    6.43 +	session_id=${tty##*/}-$$
    6.44 +	parent=`cat /proc/$PPID/cmdline 2> /dev/null`
    6.45 +	system=`uname -rs`
    6.46 +	login_from=`who | grep "${tty##/dev/}" | awk '{print $6;}' | tr -d '()'`
    6.47 +	[ -n "$bsd" ] && login_from="" #FIXME!
    6.48 +	start_time=`date +%s`
    6.49 +	hostname=`hostname -f`
    6.50  
    6.51 -	if [ -n "$this_term" ] && echo $this_term | grep -qv script
    6.52 -	then	
    6.53 -		exec script $flush -q $LMHOME/${TTY##*/}-$$.script
    6.54 -	fi
    6.55 -	# LabMaker:END 
    6.56 +	cat <<INFO > $LMHOME/${session_id}.info
    6.57 +<session>
    6.58 +<session_id>$session_id</session_id>
    6.59 +<hostname>$hostname</hostname>
    6.60 +<user>$USER</user>
    6.61 +<login_from>$login_from</login_from>
    6.62 +<tty>$tty</tty>
    6.63 +<system>$system</system>
    6.64 +<parent>$parent</parent>
    6.65 +<ppid>$PPID</ppid>
    6.66 +<pid>$$</pid>
    6.67 +<start_time>$start_time</start_time>
    6.68 +</session>
    6.69 +INFO
    6.70 +
    6.71 +	exec script $flush -q $LMHOME/${session_id}.script
    6.72 +fi
    6.73 +# LabMaker:END 
    6.74  LM_bash_profile
    6.75  	cat $temp_file > $profile
    6.76  	rm $temp_file