Subversion Repositories camp_sysinfo_client_3

Rev

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