(perl script)
Enter at your own risk :)
#!/usr/local/bin/perl # # generate user-based machine usage visualization # # print usage line and exit if wrong number of args if ($#ARGV != 1) { print "usage: machineUsage numPrevDays hours\n"; exit; } $numPrevDays = $ARGV[0]; # graph the last N days activity $hours = $ARGV[1]; # check for usage every N hours # collect all usage data $online = true; # if true, collect data from machines, otherwise look in file if($online) { $machines = `systems sgi`; # get names of all sgis chop($machines); # get rid of the return at the end @sgis = split(/ /, $machines); # split the big string into an array of machine names $lastData = ""; # look on each machine and put all results foreach $machine (@sgis) { # in one great big string called $lastData $tmp = `rsh $machine last`; # ask $machine who was on recently $lastData .= "\n$tmp"; # append answer to $lastData string } @lastData = split(/\n/, $lastData); # split all usage lines into an array } else { # just read the data from a file, prob written by a daemon open(FILE, "lastData.txt"); @lastData = <FILE>; close(FILE); } @lastData = reverse(@lastData); # put data in chron order # make an assoc array of unique usernames $numUsers = 0; foreach $line (@lastData) { $user = &getUserName($line); # filter out staff, etc (since left logged in) and root processes if(($user ne "phil") && ($user ne "mlewis") && ($user ne "tcp") && ($user ne "smay") && ($user ne "root") && ($user ne "pete") && ($user ne "spencer") && ($user ne "midori") && ($user ne "wtmp") && ($user ne "reboot") && ($user ne "csuri") && ($user ne "susskind")) { if($users{$user} == undef) { $users{$user} = $numUsers++; } } } # for each timeperiod find out usage for all users $totalTime = $numPrevDays * 24 * 3600; $time = time; $timeRez = $hours * 3600; # check usage every N seconds $timeSteps = 0; for($t = $time-$totalTime; $t < $time; $t += $timeRez) { $start = $t; $finish = $t + $timeRez - 1; # calc usage for each user for the period of time from $start to $finish %usage = computeUsage($start, $finish); # fill in one row in 2D array: i=user, j=$start time, val=cpuUsage @results = &newArray($numUsers); foreach $user (keys %usage) { $hours = int($usage{$user} * 100) / 100; $results[$users{$user}] = $hours; } $data[$timeSteps++] = [ @results ]; } # print out usage for each user #foreach $user (keys %usage) { # print "$user: "; # for($i=0; $i<$timeSteps; $i++) { # print "$data[$i][$users{$user}] "; # } # print "\n"; #} # compute total usage for each user $maxUsage = 0; foreach $user (keys %usage) { $userNum = $users{$user}; $totalUsage[$userNum] = 0; for($i=0; $i<$timeSteps; $i++) { $usage = $data[$i][$userNum]; $totalUsage[$userNum] += $usage; if($usage > $maxUsage) { $maxUsage = $usage; } } } # sort users by total usage into new array @sortedKeys = sort by_usage keys(%usage); #foreach $key (@sortedKeys) { # $userNum = $users{$key}; # print "$key: $totalUsage[$userNum]\n"; #} # make a heightfield from sorted usage data # just use top 20 users print <<EOF #VRML V2.0 utf8 Group { children [ DEF TOUCH TouchSensor {} Shape { appearance Appearance { material Material {} } geometry DEF GRID ElevationGrid { height [ EOF ; $names = ""; $colors = ""; $maxHeight = $maxUsage/2; foreach $key (@sortedKeys) { $names .= "\"$key\" "; for($x=0; $x<$timeSteps; $x++) { $userNum = $users{$key}; $height = $data[$x][$userNum]/2; print $height . " "; $red = $height/$maxHeight; $colors .= $red." ".(1-$red)." 0 "; } print "\n"; } $numKeys = @sortedKeys; $xs = $numKeys / $timeSteps; $zs = 1; print <<EOF ] color Color { color [ $colors ] } xDimension $timeSteps zDimension $numKeys xSpacing $xs zSpacing $zs solid FALSE } } ] } DEF SCRIPT Script { eventIn SFVec3f touched eventOut MFString who field MFString names [ $names ] url "vrmlscript: function touched(val) { who[0] = names[Math.round(val.z)]; } " } ROUTE TOUCH.hitPoint_changed TO SCRIPT.touched DEF NEAR ProximitySensor { size 1000 1000 1000 } DEF TT Transform { children Transform { translation -.125 .1 -.3 scale .02 .02 .02 children Shape { appearance Appearance { material Material { diffuseColor .5 .5 0 } } geometry DEF TEXT Text { } } } } ROUTE NEAR.position_changed TO TT.translation ROUTE NEAR.orientation_changed TO TT.rotation ROUTE SCRIPT.who TO TEXT.string NavigationInfo { type "EXAMINE" } EOF ; # add text label in HUD # use it on network for real (leave old code commented, can have daemon drive) exit; sub newArray() { local $n; local $i; local @tmp; $n = $_[0]; for($i=0; $i<$n; $i++) { $tmp[$i] = 0; } return @tmp; } sub computeUsage { local $fromTime; local $toTime; local $user; local $cnt; local $line; local $startTime; local $stopTime; local %usage; local $duration; $fromTime = $_[0]; $toTime = $_[1]; # examine all usage lines, collect all relevent data $cnt = 0; foreach $line (@lastData) { if(!($line =~ /^\w+ ftp/)) { $startTime = &computeStartTime($line); $stopTime = &computeStopTime($line); if(($stopTime > $fromTime) && ($startTime < $toTime)) { $releventData[$cnt++] = $line; } } } # step through all lines and collect total login times $prevStopTime = -1; $prevUser = ""; foreach $line (@releventData) { # determine start and stop times for this line $startTime = &computeStartTime($line); $stopTime = &computeStopTime($line); $user = &getUserName($line); if(($user ne "phil") && ($user ne "mlewis") && ($user ne "tcp") && ($user ne "smay") && ($user ne "root") && ($user ne "pete") && ($user ne "spencer") && ($user ne "midori") && ($user ne "wtmp") && ($user ne "reboot") && ($user ne "csuri") && ($user ne "susskind")) { $startTime = &clamp($startTime, $fromTime, $toTime); $stopTime = &clamp($stopTime, $fromTime, $toTime); # determine whether any new info in this line by comparing to info from prev line if(($user ne $prevUser) || ($startTime > $prevStopTime)) { # determine duration of login according to this line $duration = $stopTime - $startTime; # add duration to user's total: store in association list, key is user if($usage{$user} == undef) { $usage{$user} = $duration / 3600; } else { $usage{$user} += $duration / 3600; } # store user, start and stop times to compare to next line $prevUser = $user; $prevStopTime = $stopTime; } } } # return findings return %usage; } sub getUserName { $thisLine = $_[0]; if($thisLine =~ /^(\w+)/) { return $1; } else { return ""; } } sub clamp { local $v; local $hi; local $low; $v = $_[0]; $low = $_[1]; $hi = $_[2]; if($v < $low) { return $low; } elsif($v > $hi) { return $hi; } else { return $v; } } use Time::Local; sub computeStartTime { $thisLine = $_[0]; if($thisLine =~ /(\w+)\s+(\d+) (\d+)\:(\d+)\s+still logged in\s*$/) { $monStr = $1; $mon = calcMonth($monStr); $mday = $2; $startHr = $3; $startMin = $4; $timeOfLine = timelocal(0, $startMin, $startHr, $mday, $mon, 98); return $timeOfLine; } elsif($thisLine =~ /(\w+)\s+(\d+) (\d+)\:(\d+) - (\d+)\:(\d+)\s+\((\d+)\:(\d+)\)\s*$/) { $monStr = $1; $mon = calcMonth($monStr); $mday = $2; $startHr = $3; $startMin = $4; $stopHr = $5; $stopMin = $6; $durHr = $7; $durMin = $8; $timeOfLine = timelocal(0, $startMin, $startHr, $mday, $mon, 98); return $timeOfLine; } else { return -1; } } sub computeStopTime { $thisLine = $_[0]; if($line =~ /still logged in$/) { return time; } elsif($thisLine =~ /(\w+)\s+(\d+) (\d+)\:(\d+) - (\d+)\:(\d+)\s+\((\d+)\:(\d+)\)\s*$/) { $monStr = $1; $mon = calcMonth($monStr); $mday = $2; $startHr = $3; $startMin = $4; $stopHr = $5; $stopMin = $6; $durHr = $7; $durMin = $8; $timeOfLine = timelocal(0, $stopMin, $stopHr, $mday, $mon, 98); # if worked past midnight, add one day (in seconds) if($stopHr < $startHr) { $timeOfLine += 3600 * 24; } return $timeOfLine; } else { return -1; } } sub calcMonth { $monStr = $_[0]; if($monStr eq "Jan") { $mon = 0; } elsif($monStr eq "Feb") { $mon = 1; } elsif($monStr eq "Mar") { $mon = 2; } elsif($monStr eq "Apr") { $mon = 3; } elsif($monStr eq "May") { $mon = 4; } elsif($monStr eq "Jun") { $mon = 5; } elsif($monStr eq "Jul") { $mon = 6; } elsif($monStr eq "Aug") { $mon = 7; } elsif($monStr eq "Sep") { $mon = 8; } elsif($monStr eq "Oct") { $mon = 9; } elsif($monStr eq "Nov") { $mon = 10; } elsif($monStr eq "Dec") { $mon = 11; } return $mon; } sub by_usage { $userNum1 = $users{$a}; $userNum2 = $users{$b}; $totalUsage[$userNum1] <=> $totalUsage[$userNum2]; }
mrl