Subversion Repositories camp_sysinfo_client_3

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
74 rodolico 1
#! perl -w
2
# use strict; # eval doesn't work with use strict !?
3
# see POD documentation at end
4
 
96 rodolico 5
 
6
 
74 rodolico 7
=head1 NAME
8
 
9
uptime.pl - Uptime for Windows. Version 0.27.
10
 
11
=cut
12
 
96 rodolico 13
$^O eq "MSWin32" || exit;
74 rodolico 14
 
15
my $max_results = 5; # if we have to use tick counts
16
 
17
my $VERSION = 0.27;
18
 
19
my $debug = $ENV{'QUERY_STRING'} || $ARGV[0];
20
print "$0 version $VERSION\n" if $debug;
21
print "Debug mode on\n" if $debug;
22
print "Perl version $]\n" if $debug;
23
 
24
BEGIN {
96 rodolico 25
   # HTTP headers if needed
26
   local $^W = 0;
27
   print "$ENV{'SERVER_PROTOCOL'}/200 OK\n" if $ENV{'PERLXS'} eq "PerlIS";
28
   print "Content-type: text/plain\n\n" if $ENV{'SERVER_PROTOCOL'};
74 rodolico 29
}
30
 
31
my ($several, @uptimes);
32
 
33
if (Win32::IsWinNT()) {
96 rodolico 34
   print "Windows NT\n\n" if $debug;
35
   push @uptimes, (&event_log || &tick_counts);
36
   print "eval error: $@\n" if $@ && $debug;
74 rodolico 37
}
38
else {
96 rodolico 39
   print "Windows 9x\n\n" if $debug;
40
   push @uptimes, (&system_da0 || &tick_counts);
74 rodolico 41
}
42
 
43
sub tick_counts {
96 rodolico 44
   print "Counting ticks\n" if $debug;
45
   my @ticks;
46
   my $ticks = Win32::GetTickCount() > 0
47
            ? Win32::GetTickCount()
48
           : Win32::GetTickCount() + 2**32;
49
   my $seconds = $ticks/1000;
50
   for (1..$max_results-1) {
51
      push @ticks, time()-$seconds;
52
      $seconds += 2**32/1000;
53
   }
54
   return @ticks, time()-$seconds;
74 rodolico 55
}
56
 
57
sub system_da0 {
96 rodolico 58
   my $file = "$ENV{'WINDIR'}\\system.da0";
59
   print "Checking $file\n" if $debug;
60
   my $stat = (stat $file)[9]; 
61
   print "Could not stat $file ($!)\n" if $debug && !$stat;
62
   return $stat || undef;
74 rodolico 63
}
64
 
65
sub event_log {
96 rodolico 66
   my $result = eval '
74 rodolico 67
        local $^W = 0;
96 rodolico 68
      use Win32::EventLog;
69
      my ($EventLog, $first, $count, $event, %data);
70
      Win32::EventLog::Open($EventLog , "System", "") || die ("EventLog Open() failed");
71
      $EventLog->GetOldest($first) || die ("EventLog GetOldest() failed");
72
      $EventLog->GetNumber($count) || die ("EventLog GetNumber() failed");
73
      print "Event log first=$first, count=$count\n" if $debug;
74 rodolico 74
 
96 rodolico 75
      $EventLog->Read((EVENTLOG_SEEK_READ | EVENTLOG_BACKWARDS_READ),$first+$count,$event);
74 rodolico 76
 
96 rodolico 77
      for $i (0 .. $first+$count-1) {
78
         $EventLog->Read((EVENTLOG_SEQUENTIAL_READ|EVENTLOG_BACKWARDS_READ),0,$event)
79
             || die ("EventLog Read() failed at event $i");
74 rodolico 80
 
96 rodolico 81
         %data = %{$event};
82
         $data{"EventID"} = $data{"EventID"} & 0xffff;
74 rodolico 83
 
96 rodolico 84
          next unless $data{"EventID"} == 6005;
85
         print "Found event 6005\n" if $debug;
86
         return $data{"TimeGenerated"};
87
         print "This script is broken: it should never reach this line\n";
88
      }
89
      return undef;
90
   ';
91
   if ($@) {
92
      print "Eval error: $@\n";
93
      return undef;
94
   }
95
   else {
96
      return $result;
97
   }
74 rodolico 98
}
99
 
100
$several = @uptimes - 1;
101
foreach (@uptimes) {
96 rodolico 102
   print "up ", &time2days($_), " (since ", scalar localtime($_), ")\n";
103
   print "or:\n" if $several;
74 rodolico 104
}
105
 
106
print "... but who would believe that anyway?...\n" if $several;
107
 
108
sub time2days {
96 rodolico 109
   print "converting $_[0]\n" if $debug;
110
   my $days = (time() - $_[0])/(24*60*60);
111
   my $hours = ($days - int($days)) * 24;
112
   my $minutes = ($hours - int($hours)) * 60;
113
   my $day_st = $days >= 2 ? 'days' : 'day';
114
   return sprintf("%0d $day_st %02d:%02d", $days, $hours, $minutes);
74 rodolico 115
}
116
 
117
__END__
118
 
119
=head1 SYNOPSIS
120
 
121
perl uptime.pl [debug]
122
 
123
=head1 DESCRIPTION
124
 
125
Report machine uptime on Windows systems.
126
 
127
This script attempts to report the system uptime in a format similar
128
to the Unix uptime command. It only reports uptime, not users or
129
load statistics.
130
 
131
On NT it uses the event log. The event log service itself writes an
132
entry to it when it starts (ID 6005).
133
 
134
On Win95 it gets the create time of the system.da0 file (the system.dat
135
backup file which is recreated at system start).
136
 
137
If eihter of these methods fail (like on Win98), it uses the system tick 
138
counts. Since these can only hold about 49.7 days, it returns a list of 
139
possible uptimes, limited to C<$max_results> (5 by default). (Have you ever 
140
seen a Windows system up for more than 200 days? ;-) If yes, set 
141
C<$max_results> to a higher value).
142
 
143
The script can be used in CGI. It will print the needed headers automatically.
144
 
145
The latest version should always be available at
146
http://alma.ch/perl/scripts/uptime.pl
147
 
148
=head1 OPTIONS
149
 
150
If given any argument (at the command line or as a CGI argument), it is
151
considered as a 'debug' or 'verbose' option, and additional stuff is printed.
152
 
153
=head1 FEATURES (aka BUGS)
154
 
155
On NT, the uptime will be wrong if you restarted the event log service.
156
 
157
If you have a low limit on your event log file size or logged events, and
158
your system has been up for a long time, the event may not be available
159
anymore. The script will then use tick counts.
160
 
161
On Win95, the uptime will be wrong if the create time of your system.da0 file
162
is not the same as when your system booted. I don't see what could cause this
163
unless you overwrite the file, but there may be special cases. Let me know if
164
you find any.
165
 
166
On Win98, there seems to be no way other than tick counts. Let me know if you
167
find something better.
168
 
169
=head1 SCRIPT CATEGORIES
170
 
171
Win32
172
 
173
=head1 OSNAMES
174
 
175
MSWin32
176
 
177
=head1 AUTHOR
178
 
179
M. Ivkovic. email: C<perl -e "printf '%s@%s', 'mi.perl', 'alma.ch'">.
180
 
181
Others welcome to extend it to more operating systems which don't have an uptime 
182
command.
183
 
184
=head1 COPYRIGHT
185
 
186
Copyright M. Ivkovic, 1999. Same license as Perl itself.
187
 
188
=head1 README
189
 
190
Attempt to report machine uptime on various Windows systems.
191
 
192
=cut