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