| rev | line source | 
| devi@0 | 1 #!/usr/bin/perl | 
| devi@0 | 2 | 
| devi@0 | 3 | 
| devi@0 | 4 use strict; | 
| devi@0 | 5 use Inline::Files; | 
| devi@0 | 6 use Data::Dumper; | 
| devi@0 | 7 use Switch; | 
| devi@0 | 8 use XML::Simple; | 
| devi@0 | 9 use Getopt::Long; | 
| devi@4 | 10 use utf8; | 
| devi@0 | 11 | 
| devi@0 | 12 our $XMLClass; | 
| devi@0 | 13 our $XMLCourse; | 
| devi@0 | 14 our @Labs; | 
| devi@0 | 15 | 
| devi@0 | 16 our %Machines;			# Machines list from class.xml | 
| devi@0 | 17 our @SelectedMachines;		# Machines list given as the command line argument | 
| devi@0 | 18 | 
| devi@0 | 19 our $Config_File = "labmaker.conf"; | 
| devi@0 | 20 our %Config = ( | 
| devi@0 | 21 	"show_host" 	=> "no", | 
| devi@0 | 22 | 
| devi@3 | 23 	# Вспомогательные программы | 
| devi@3 | 24 	"l3-report"	=> "./lm-report", | 
| devi@3 | 25 | 
| devi@0 | 26 	# Каталоги | 
| devi@0 | 27 	"path_labmaker" => "/var/labmaker/", | 
| devi@0 | 28 	"path_classes"	=> "/var/labmaker/classes/", | 
| devi@3 | 29 	"path_lablogs"	=> "/var/labmaker/lablogs/", | 
| devi@0 | 30 	"courses_path"	=> "/var/labmaker/courses/", | 
| devi@0 | 31 	"outpath"	=> "/var/labmaker/out/", | 
| devi@3 | 32 	"path_web"	=> "/var/www/l3",		# Путь к web-отчётам | 
| devi@3 | 33 	"path_share"	=> "./share/",		# Путь к web-отчётам | 
| devi@0 | 34 | 
| devi@0 | 35 	# Файлы | 
| devi@0 | 36 	"runfile"	=> "lm.run", | 
| devi@0 | 37 	"logfile"	=> "lm.log", | 
| devi@0 | 38 | 
| devi@0 | 39 	"class" 	=> "class", 				# Имя файла класса | 
| devi@0 | 40 	"class_suffix" 	=> ".xml", 				# Cуффикс файла класса | 
| devi@0 | 41 | 
| devi@0 | 42 	"sshkey"	=> "$ENV{HOME}/.ssh/id_dsa.pub", | 
| devi@0 | 43 	"lmssh"		=> "./lm-ssh", | 
| devi@0 | 44 	"lminstall"	=> "./lm-install", | 
| devi@0 | 45 	"ssh_user"	=> "r", | 
| devi@0 | 46 ); | 
| devi@0 | 47 | 
| devi@0 | 48 our %Run = ( | 
| devi@0 | 49 	"lab" => "" | 
| devi@0 | 50 ); | 
| devi@0 | 51 | 
| devi@0 | 52 our %Scripts; | 
| devi@0 | 53 | 
| devi@0 | 54 sub load_class; | 
| devi@0 | 55 sub load_config; | 
| devi@0 | 56 sub load_course; | 
| devi@0 | 57 sub load_scripts; | 
| devi@0 | 58 | 
| devi@0 | 59 sub lm_next; | 
| devi@0 | 60 sub lm_prev; | 
| devi@0 | 61 sub lm_start; | 
| devi@0 | 62 sub lm_stop; | 
| devi@0 | 63 sub lm_set; | 
| devi@0 | 64 sub lm_do; | 
| devi@0 | 65 sub lm_report; | 
| devi@0 | 66 sub lm_show_hosts; | 
| devi@0 | 67 sub lm_show_labs; | 
| devi@0 | 68 | 
| devi@0 | 69 sub load_run; | 
| devi@0 | 70 sub save_run; | 
| devi@0 | 71 sub print_log; | 
| devi@0 | 72 sub print_usage_info; | 
| devi@0 | 73 sub main(); | 
| devi@0 | 74 | 
| devi@0 | 75 main(); | 
| devi@0 | 76 | 
| devi@0 | 77 sub main() | 
| devi@0 | 78 { | 
| devi@0 | 79 	binmode STDOUT, ":utf8"; | 
| devi@0 | 80 | 
| devi@0 | 81 	if (! @ARGV) { | 
| devi@0 | 82 		print_usage_info(); | 
| devi@0 | 83 		exit(0); | 
| devi@0 | 84 	} | 
| devi@0 | 85 | 
| devi@0 | 86 	load_config; | 
| devi@0 | 87 	load_run; | 
| devi@0 | 88 	load_scripts; | 
| devi@0 | 89 	load_class; | 
| devi@0 | 90 	load_course; | 
| devi@0 | 91 | 
| devi@0 | 92 	my $arg = join " ", @ARGV; | 
| devi@0 | 93 | 
| devi@0 | 94 	# Getting @SelectedMachines if any | 
| devi@0 | 95 	if ($arg =~ s/@(.*?)\s//) { | 
| devi@0 | 96 		my $machines = $1; | 
| devi@0 | 97 		my @list = split /,/, $machines; | 
| devi@0 | 98 		for my $interval (@list) { | 
| devi@0 | 99 			my ($first, $last) = split /-/, $interval; | 
| devi@0 | 100 | 
| devi@0 | 101 			push @SelectedMachines, $first; | 
| devi@0 | 102 			while ($first < $last) { | 
| devi@0 | 103 				push @SelectedMachines, ++$first; | 
| devi@0 | 104 			} | 
| devi@0 | 105 		} | 
| devi@0 | 106 	} | 
| devi@0 | 107 | 
| devi@0 | 108 	# Choose command to do | 
| devi@0 | 109 	switch ($arg) { | 
| devi@0 | 110 		case "next"	{ lm_next } | 
| devi@0 | 111 		case "prev"	{ lm_prev } | 
| devi@0 | 112 		case /set /	{ $arg =~ /set (.*)/; lm_set $1 } | 
| devi@0 | 113 		case "report"	{ lm_report } | 
| devi@0 | 114 		case "start"	{ lm_start } | 
| devi@0 | 115 		case "stop"	{ lm_stop } | 
| devi@0 | 116 		case "show hosts" { lm_show_hosts } | 
| devi@0 | 117 		case "show labs" { lm_show_labs } | 
| devi@0 | 118 		case /do /  { $arg =~ /do (.*)/;  lm_do "$1" } | 
| devi@0 | 119 		else 		{ print_usage_info() } | 
| devi@0 | 120 	} | 
| devi@0 | 121 	save_run; | 
| devi@0 | 122 	exit(0); | 
| devi@0 | 123 } | 
| devi@0 | 124 | 
| devi@0 | 125 sub load_scripts | 
| devi@0 | 126 { | 
| devi@0 | 127 	local $/; | 
| devi@0 | 128 	$_=<SCRIPTS>; | 
| devi@0 | 129 	%Scripts = ("empty-element", split (/###(.*)\n/)); | 
| devi@0 | 130 	delete($Scripts{"empty-element"}); | 
| devi@0 | 131 } | 
| devi@0 | 132 | 
| devi@0 | 133 sub load_config | 
| devi@0 | 134 { | 
| devi@0 | 135 	my %file_config; | 
| devi@0 | 136 	my %argv_config; | 
| devi@0 | 137 	#read_config_file(\%file_config, $Config_File); | 
| devi@0 | 138 	GetOptions(\%argv_config, map "$_=s", keys %Config); | 
| devi@0 | 139 	%Config = (%Config, %file_config, %argv_config); | 
| devi@0 | 140 } | 
| devi@0 | 141 | 
| devi@0 | 142 sub load_course | 
| devi@0 | 143 { | 
| devi@0 | 144 	$XMLCourse = XMLin($Config{"courses_path"}.$XMLClass->{"course"}.".xml", ForceArray => 1 ) | 
| devi@0 | 145 		or die "Can't open file of the course ",$XMLClass->{"course"}," [with .xml extension]\n"; | 
| devi@0 | 146 #	print Dumper($XMLCourse); | 
| devi@0 | 147 	for my $lab (@{$XMLCourse->{"module"}}) { | 
| devi@0 | 148 		push @Labs, $lab->{"code"}; | 
| devi@0 | 149 	} | 
| devi@0 | 150 } | 
| devi@0 | 151 | 
| devi@0 | 152 sub load_class | 
| devi@0 | 153 { | 
| devi@0 | 154 	my $classfile = | 
| devi@0 | 155 	$Config{"path_classes"}."/".$Config{"class"}.$Config{"class_suffix"}; | 
| devi@0 | 156 	$XMLClass = XMLin($classfile , ForceArray => [ 'student' ] ) | 
| devi@0 | 157 		or die "Can't open file of the class ",$classfile,"\n"; | 
| devi@0 | 158 | 
| devi@0 | 159 	for my $student (@{$XMLClass->{"student"}}) { | 
| devi@0 | 160 		$Machines{$student->{"host"}} = { | 
| devi@0 | 161 			"name"	=> "$student->{firstname} $student->{surname}", | 
| devi@0 | 162 			"user"	=> "$student->{user}", | 
| devi@0 | 163 			"student" => $student, | 
| devi@0 | 164 		} | 
| devi@0 | 165 	} | 
| devi@0 | 166 #	print Dumper($XMLClass); | 
| devi@0 | 167 #	print Dumper(\%Machines); | 
| devi@0 | 168 } | 
| devi@0 | 169 | 
| devi@0 | 170 | 
| devi@0 | 171 sub lm_next | 
| devi@0 | 172 { | 
| devi@0 | 173 	for(my $i=0; $i<=$#Labs; $i++){ | 
| devi@0 | 174 		if ( $Labs[$i] eq $Run{"lab"} ) { | 
| devi@0 | 175 			if ($i < $#Labs) { | 
| devi@0 | 176 				lm_set($Labs[$i+1]); | 
| devi@0 | 177 				return ; | 
| devi@0 | 178 			} else { | 
| devi@0 | 179 				die "Lab ", $Run{"lab"}, " is the last. Switch to next lab is impossible" | 
| devi@0 | 180 			} | 
| devi@0 | 181 		} | 
| devi@0 | 182 | 
| devi@0 | 183 	} | 
| devi@0 | 184 	die "Lab ", $Run{"lab"}, " not found. Don't know which is next" | 
| devi@0 | 185 } | 
| devi@0 | 186 | 
| devi@0 | 187 sub lm_prev | 
| devi@0 | 188 # Switch to previous lab | 
| devi@0 | 189 { | 
| devi@0 | 190 	for(my $i=0; $i<=$#Labs; $i++){ | 
| devi@0 | 191 		if ( $Labs[$i] eq $Run{"lab"} ) { | 
| devi@0 | 192 			if ($i > 0) { | 
| devi@0 | 193 				lm_set($Labs[$i-1]); | 
| devi@0 | 194 				return ; | 
| devi@0 | 195 			} else { | 
| devi@0 | 196 				die "Lab ", $Run{"lab"}, " is the first. Switch to previous lab is impossible" | 
| devi@0 | 197 			} | 
| devi@0 | 198 		} | 
| devi@0 | 199 | 
| devi@0 | 200 	} | 
| devi@0 | 201 	die "Lab ", $Run{"lab"}, " not found. Don't know which is previous" | 
| devi@0 | 202 } | 
| devi@0 | 203 | 
| devi@0 | 204 sub lm_set | 
| devi@0 | 205 # Switch to $_[0] lab | 
| devi@0 | 206 # FIXME | 
| devi@0 | 207 { | 
| devi@0 | 208 	my $lab = shift; | 
| devi@0 | 209 	print "Current lab is $lab\n"; | 
| devi@0 | 210 	$Run{"lab"} = "$lab"; | 
| devi@0 | 211 	lm_do "setlab", $lab; | 
| devi@0 | 212 } | 
| devi@0 | 213 | 
| devi@0 | 214 | 
| devi@0 | 215 sub lm_start | 
| devi@0 | 216 # Start new training day | 
| devi@0 | 217 { | 
| devi@0 | 218 	print_log(`date`." STARTED\n"); | 
| devi@0 | 219 	if ($Run{"lab"}) { | 
| devi@0 | 220 		lm_next; | 
| devi@0 | 221 	} | 
| devi@0 | 222 	else | 
| devi@0 | 223 	{ | 
| devi@0 | 224 		# First lab in the course | 
| devi@0 | 225 		lm_set($Labs[0]); | 
| devi@0 | 226 	} | 
| devi@0 | 227 } | 
| devi@0 | 228 | 
| devi@0 | 229 sub lm_stop | 
| devi@0 | 230 # Stop this training day | 
| devi@0 | 231 { | 
| devi@0 | 232 	print_log(`date`." STOPPED\n"); | 
| devi@0 | 233 } | 
| devi@0 | 234 | 
| devi@0 | 235 | 
| devi@0 | 236 sub lm_show_hosts | 
| devi@0 | 237 # Show hosts used to run a commands | 
| devi@0 | 238 { | 
| devi@0 | 239 	my $i=1; | 
| devi@0 | 240 	for my $m (sort keys %Machines) { | 
| devi@0 | 241 		if (!@SelectedMachines || grep /^$i$/, @SelectedMachines) { | 
| devi@0 | 242 			print "($i)","\t",$m,"\t",$Machines{$m}->{"name"},"\n"; | 
| devi@0 | 243 		} | 
| devi@0 | 244 		$i++; | 
| devi@0 | 245 	} | 
| devi@0 | 246 } | 
| devi@0 | 247 | 
| devi@0 | 248 sub lm_show_labs | 
| devi@0 | 249 # Show hosts used to run a commands | 
| devi@0 | 250 { | 
| devi@0 | 251 	my $i=1; | 
| devi@0 | 252 	for my $lab (@Labs) { | 
| devi@0 | 253 		print $lab; | 
| devi@0 | 254 		print "*" if $lab eq $Run{"lab"}; | 
| devi@0 | 255 		print "\n"; | 
| devi@0 | 256 	} | 
| devi@0 | 257 } | 
| devi@0 | 258 | 
| devi@0 | 259 sub lm_do | 
| devi@0 | 260 # Do the $_[0] command on all of the hosts | 
| devi@0 | 261 { | 
| devi@0 | 262 	my $command = shift; | 
| devi@0 | 263 	my $arg = join " ", @_; | 
| devi@0 | 264 	my $i=1; | 
| devi@0 | 265 	for my $m (sort keys %Machines) { | 
| devi@0 | 266 		if (!@SelectedMachines || grep $_ eq $i, @SelectedMachines) { | 
| devi@0 | 267 			print "$m:\n" if $Config{"show_host"} =~ /y/i; | 
| devi@0 | 268 | 
| devi@0 | 269 			my %myenv = ( %Config, | 
| devi@0 | 270 				host 	=>	$m, | 
| devi@0 | 271 				dirs	=>	"/root /home/".$Machines{$m}->{"user"}, | 
| devi@3 | 272 				lablogs =>	$Config{"path_lablogs"}."/". | 
| devi@0 | 273 						$XMLClass->{"course"}."/". | 
| devi@0 | 274 						$XMLClass->{"date"}."/". | 
| devi@0 | 275 						"$m", | 
| devi@0 | 276 				lab	=> 	$arg, | 
| devi@0 | 277 | 
| devi@0 | 278 				email	=>	$Machines{$m}->{"student"}->{"email"}, | 
| devi@0 | 279 				company	=>	$Machines{$m}->{"student"}->{"company"}, | 
| devi@0 | 280 				center 	=>	$XMLClass->{"center"}, | 
| devi@0 | 281 				course 	=>	$XMLClass->{"course"}, | 
| devi@0 | 282 				date 	=>	$XMLClass->{"date"}, | 
| devi@0 | 283 				name	=> 	$Machines{$m}->{"name"}, | 
| devi@0 | 284 				coursepath =>	$XMLCourse->{"path"}, | 
| devi@0 | 285 | 
| devi@0 | 286 			); | 
| devi@0 | 287 			if (grep { $_ eq $command} keys %Scripts) { | 
| devi@0 | 288 				$_=$Scripts{"$command"}; | 
| devi@0 | 289 				s/\$(\w+)/$myenv{$1}/ge; | 
| devi@0 | 290 				open(SHELL, "|/bin/sh -s"); | 
| devi@0 | 291 				binmode SHELL, ":utf8"; | 
| devi@0 | 292 				print SHELL $_; | 
| devi@0 | 293 				close (SHELL); | 
| devi@0 | 294 			} | 
| devi@0 | 295 			else { | 
| devi@0 | 296 				my $res = `ssh $Config{"ssh_user"}\@$m $command`; | 
| devi@0 | 297 				if ($res) { | 
| devi@0 | 298 					my $count = ($res =~ s/(^)/$m: /mg); | 
| devi@0 | 299 					print $res; | 
| devi@0 | 300 					print "\n" if ($count > 1); | 
| devi@0 | 301 				} | 
| devi@0 | 302 			} | 
| devi@0 | 303 		} | 
| devi@0 | 304 		$i++; | 
| devi@0 | 305 	} | 
| devi@0 | 306 } | 
| devi@0 | 307 | 
| devi@0 | 308 | 
| devi@3 | 309 | 
| devi@3 | 310 =cut comment | 
| devi@3 | 311 | 
| devi@3 | 312 lm report | 
| devi@3 | 313 | 
| devi@3 | 314 Построить html представление для журналов текущего класса. | 
| devi@3 | 315 Для построения используется скрипт l3-report. | 
| devi@3 | 316 | 
| devi@3 | 317 =cut | 
| devi@3 | 318 | 
| devi@0 | 319 sub lm_report | 
| devi@0 | 320 { | 
| devi@0 | 321 | 
| devi@3 | 322 	my $webdir = $Config{"path_web"}; | 
| devi@3 | 323 	my $course=$XMLClass->{"course"}; | 
| devi@3 | 324 	my $date=$XMLClass->{"date"}; | 
| devi@3 | 325 	my $encoding=$XMLClass->{"charset"}; | 
| devi@0 | 326 | 
| devi@4 | 327 	my $center = $XMLClass->{"center"}; | 
| devi@4 | 328 	my $instructor = $XMLClass->{"instructor"}->{"firstname"}." ".$XMLClass->{"instructor"}->{"surname"}; | 
| devi@4 | 329 	my $course_name = $XMLCourse->{"fullname"}[0]; | 
| devi@4 | 330 | 
| devi@4 | 331 	# Индекс для данного класса | 
| devi@4 | 332 | 
| devi@4 | 333 	my $head; | 
| devi@4 | 334 | 
| devi@4 | 335 	$head="Журналы лабораторных работ"; | 
| devi@4 | 336 	open(HTML, ">$webdir/$date/index.html") | 
| devi@4 | 337 		or die "Can't open $webdir/$date/index.html for writing"; | 
| devi@4 | 338 	binmode HTML, ":utf8"; | 
| devi@4 | 339 	print HTML <<HEAD; | 
| devi@4 | 340 	<html> | 
| devi@4 | 341 	<head> | 
| devi@4 | 342 	<meta content='text/html; charset=utf-8' http-equiv='Content-Type' /> | 
| devi@4 | 343 	<title>$head</title> | 
| devi@4 | 344 	</head> | 
| devi@4 | 345 	<body> | 
| devi@4 | 346 	<h1>$head</h1> | 
| devi@4 | 347 	<p> | 
| devi@4 | 348 	Курс: $course_name ($course)<br/> | 
| devi@4 | 349 	Начало: $date<br/> | 
| devi@4 | 350 	Учебный центр: $center <br/> | 
| devi@4 | 351 	Инструктор: $instructor <br/> | 
| devi@4 | 352 	</p> | 
| devi@4 | 353 	<table> | 
| devi@4 | 354 HEAD | 
| devi@4 | 355 	for my $student (@{$XMLClass->{"student"}}) { | 
| devi@4 | 356 		my $user = $student->{"user"}; | 
| devi@4 | 357 		my $hostname = $student->{"host"}; | 
| devi@4 | 358 		print HTML "<tr>\n"; | 
| devi@4 | 359 		print HTML "<td>",$student->{"firstname"}," ",$student->{"surname"},"</td>\n"; | 
| devi@4 | 360 		print HTML "<td>",$hostname,"</td>\n"; | 
| devi@4 | 361 		print HTML "<td><a href=\"$hostname/$user.html\">",$user,"</td>\n"; | 
| devi@4 | 362 		print HTML "<td><a href=\"$hostname/root.html\">","root","</td>\n"; | 
| devi@4 | 363 		print HTML "</tr>\n"; | 
| devi@4 | 364 	} | 
| devi@4 | 365 	print HTML <<TAIL; | 
| devi@4 | 366 	</table> | 
| devi@4 | 367 	</html> | 
| devi@4 | 368 TAIL | 
| devi@4 | 369 	close (HTML); | 
| devi@4 | 370 	exit; | 
| devi@4 | 371 | 
| devi@4 | 372 	# Собственно журналы | 
| devi@0 | 373 | 
| devi@3 | 374 	for my $student (@{$XMLClass->{"student"}}) { | 
| devi@3 | 375 		my $user = $student->{"user"}; | 
| devi@3 | 376 		my $hostname = $student->{"host"}; | 
| devi@3 | 377 		my $encoding = $student->{"encoding"}; | 
| devi@0 | 378 | 
| devi@3 | 379 		system("mkdir -p $webdir/$date/$hostname"); | 
| devi@3 | 380 		system("cp ".$Config{"path_share"}."/*.{ico,css} $webdir/$date/$hostname"); | 
| devi@3 | 381 		system($Config{"l3-report"}. | 
| devi@3 | 382 			" --input ".$Config{"path_lablogs"}."/$course/$date/$hostname/$user". | 
| devi@3 | 383 			" --diffs ".$Config{"path_lablogs"}."/$course/$date/$hostname/$user ". | 
| devi@3 | 384 				   $Config{"path_lablogs"}."/$course/$date/$hostname/root". | 
| devi@3 | 385 			" --output $webdir/$date/$hostname/$user.html". | 
| devi@3 | 386 			" --encoding $encoding" | 
| devi@3 | 387 		); | 
| devi@3 | 388 		system($Config{"l3-report"}. | 
| devi@3 | 389 			" --input ".$Config{"path_lablogs"}."/$course/$date/$hostname/root". | 
| devi@3 | 390 			" --diffs ".$Config{"path_lablogs"}."/$course/$date/$hostname/root ". | 
| devi@3 | 391 			" --output $webdir/$date/$hostname/root.html". | 
| devi@3 | 392 			" --encoding $encoding" | 
| devi@3 | 393 		); | 
| devi@3 | 394 	} | 
| devi@4 | 395 | 
| devi@4 | 396 | 
| devi@4 | 397 | 
| devi@0 | 398 } | 
| devi@0 | 399 | 
| devi@0 | 400 sub load_run | 
| devi@0 | 401 { | 
| devi@0 | 402 	my $runfile = $Config{"path_labmaker"}."/".$Config{"path_runfile"}; | 
| devi@0 | 403 	open (RUN, $runfile) | 
| devi@0 | 404 		or return; | 
| devi@0 | 405 	while (<RUN>) { | 
| devi@0 | 406 		chomp; | 
| devi@0 | 407 		my ($var, $val) = split /\s+/,$_,2; | 
| devi@0 | 408 		$Run{$var}=$val; | 
| devi@0 | 409 	} | 
| devi@0 | 410 	close (RUN); | 
| devi@0 | 411 } | 
| devi@0 | 412 | 
| devi@0 | 413 sub save_run | 
| devi@0 | 414 { | 
| devi@0 | 415 	my $runfile = $Config{"path_labmaker"}."/".$Config{"path_runfile"}; | 
| devi@0 | 416 	open (RN, "$runfile") | 
| devi@0 | 417 		or die "Can't save running state to $runfile"; | 
| devi@0 | 418 	for my $var (keys %Run) { | 
| devi@0 | 419 		print RN $var,"\t",$Run{$var},"\n"; | 
| devi@0 | 420 	} | 
| devi@0 | 421 	close (RN); | 
| devi@0 | 422 } | 
| devi@0 | 423 | 
| devi@0 | 424 sub print_log | 
| devi@0 | 425 { | 
| devi@0 | 426 	my $logfile = $Config{"path_labmaker"}."/".$Config{"path_logfile"}; | 
| devi@0 | 427 	open (LOG, ">>$logfile") | 
| devi@0 | 428 		or die "Can't open logfile $logfile for writing"; | 
| devi@0 | 429 	print LOG  @_; | 
| devi@0 | 430 	close (LOG); | 
| devi@0 | 431 } | 
| devi@0 | 432 | 
| devi@0 | 433 | 
| devi@0 | 434 sub print_usage_info | 
| devi@0 | 435 { | 
| devi@0 | 436 	print "Usage:\n\n\t$0 [host-list] command\n"; | 
| devi@0 | 437 	while (<USAGE>) { | 
| devi@0 | 438 		print $_; | 
| devi@0 | 439 	} | 
| devi@0 | 440 } | 
| devi@0 | 441 | 
| devi@0 | 442 __USAGE__ | 
| devi@0 | 443 | 
| devi@0 | 444 Commands: | 
| devi@0 | 445 | 
| devi@0 | 446 	next		-- next lab | 
| devi@0 | 447 	prev		-- prev lab | 
| devi@0 | 448 	set LAB		-- set current lab to LAB | 
| devi@0 | 449 	start		-- start this day training | 
| devi@0 | 450 	stop		-- stop this day training | 
| devi@0 | 451 	show hosts	-- show available hosts in the class | 
| devi@0 | 452 	show labs	-- show available labs in the course | 
| devi@0 | 453 	do COMMAND	-- do specified command on the hosts of hostlist | 
| devi@0 | 454 	report		-- generate XML/HTML reports | 
| devi@0 | 455 | 
| devi@0 | 456 | 
| devi@0 | 457 do commands: | 
| devi@0 | 458 | 
| devi@0 | 459 	install [PROFILE] -- install profile | 
| devi@0 | 460 | 
| devi@0 | 461 Host list: | 
| devi@0 | 462 | 
| devi@0 | 463 	@N		-- machine N | 
| devi@0 | 464 	@N1-N2		-- all of the machines from N1 to N2 | 
| devi@0 | 465 	@N1,N2,N3	-- machine N1, N2 and N3 | 
| devi@0 | 466 | 
| devi@0 | 467 	N* is numbers or domain names of the machines. | 
| devi@0 | 468 | 
| devi@0 | 469 	If host list is not specified, | 
| devi@0 | 470 	command is executed on all of the machines | 
| devi@0 | 471 | 
| devi@0 | 472 | 
| devi@0 | 473 | 
| devi@0 | 474 __SCRIPTS__ | 
| devi@0 | 475 ###install | 
| devi@0 | 476 cat $sshkey | $lmssh $ssh_user@$host /bin/sh -c '"mkdir -p ~/.ssh; cat >>~/.ssh/authorized_keys; chmod 600 ~/.ssh/authorized_keys"' | 
| devi@0 | 477 | 
| devi@0 | 478 ###install-lm | 
| devi@0 | 479 cat $lminstall | ssh $ssh_user@$host /bin/sh -s $dirs | 
| devi@0 | 480 | 
| devi@0 | 481 ###copy-lablogs | 
| devi@0 | 482 for i in $dirs | 
| devi@0 | 483 do | 
| devi@0 | 484 	mkdir -p $lablogs/${i##*/} | 
| devi@0 | 485 	scp -q $ssh_user@$host:${i}/.labmaker/* $lablogs/${i##*/} | 
| devi@0 | 486 done | 
| devi@0 | 487 | 
| devi@0 | 488 ###setlab | 
| devi@0 | 489 for i in $dirs | 
| devi@0 | 490 do | 
| devi@0 | 491 	echo $lab | ssh $ssh_user@$host "cat > "${i}"/.labmaker/lab" | 
| devi@0 | 492 done | 
| devi@0 | 493 | 
| devi@0 | 494 ###makeout | 
| devi@0 | 495 common=$course-$date | 
| devi@0 | 496 personal=$course-$date-$email | 
| devi@0 | 497 mkdir -p $outpath/${common}/{Lablogs,Docs} | 
| devi@0 | 498 mkdir -p $outpath/${personal}/{Course,Files} | 
| devi@0 | 499 cd $outpath/${personal} | 
| devi@0 | 500 ln -s ../${common}/Lablogs . | 
| devi@0 | 501 ln -s ../${common}/Docs . | 
| devi@0 | 502 cd ~- | 
| devi@0 | 503 export UG_PERSONAL=${PWD}/$outpath/${personal}/Course | 
| devi@0 | 504 export UG_CENTER="$center" | 
| devi@0 | 505 export UG_COURSE="$course" | 
| devi@0 | 506 export UG_DATE="$date" | 
| devi@0 | 507 export UG_STUDENT="$name" | 
| devi@0 | 508 export UG_COMPANY="$company" | 
| devi@0 | 509 cd $coursepath; make personal; cd ~- | 
| devi@0 | 510 | 
| devi@0 | 511 ###watch | 
| devi@0 | 512 cat taillast.pl | ssh $ssh_user@$host perl - /root/.labmaker |