lilalo

diff l3-agent @ 27:098664cf339c

Выполнены шаги 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 ba4d6515b8fd
children 450b6ac9b657
line diff
     1.1 --- a/l3-agent	Thu Nov 03 17:49:56 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