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