niceload: minimal --sensor support.

This commit is contained in:
Ole Tange 2012-11-09 16:51:38 +01:00
parent 00a2b4d119
commit ce02b6f794
2 changed files with 121 additions and 8 deletions

View file

@ -59,6 +59,8 @@ if(not defined $::opt_run_mem) { $::opt_run_mem = $::opt_mem; }
if(not defined $::opt_start_noswap) { $::opt_start_noswap = $::opt_noswap; }
if(not defined $::opt_run_noswap) { $::opt_run_noswap = $::opt_noswap; }
if(defined $::opt_load) { multiply_binary_prefix($::opt_load); }
my $limit = Limit->new();
my $process = Process->new($::opt_nice,@ARGV);
if($::opt_pid) {
@ -89,6 +91,37 @@ while($process->is_alive()) {
exit($::exitstatus);
sub multiply_binary_prefix {
# Evalualte numbers with binary prefix
# k=10^3, m=10^6, g=10^9, t=10^12, p=10^15, e=10^18, z=10^21, y=10^24
# K=2^10, M=2^20, G=2^30, T=2^40, P=2^50, E=2^70, Z=2^80, Y=2^80
# Ki=2^10, Mi=2^20, Gi=2^30, Ti=2^40, Pi=2^50, Ei=2^70, Zi=2^80, Yi=2^80
# ki=2^10, mi=2^20, gi=2^30, ti=2^40, pi=2^50, ei=2^70, zi=2^80, yi=2^80
# 13G = 13*1024*1024*1024 = 13958643712
my $s = shift;
$s =~ s/k/*1000/g;
$s =~ s/M/*1000*1000/g;
$s =~ s/G/*1000*1000*1000/g;
$s =~ s/T/*1000*1000*1000*1000/g;
$s =~ s/P/*1000*1000*1000*1000*1000/g;
$s =~ s/E/*1000*1000*1000*1000*1000*1000/g;
$s =~ s/Z/*1000*1000*1000*1000*1000*1000*1000/g;
$s =~ s/Y/*1000*1000*1000*1000*1000*1000*1000*1000/g;
$s =~ s/X/*1000*1000*1000*1000*1000*1000*1000*1000*1000/g;
$s =~ s/Ki?/*1024/gi;
$s =~ s/Mi?/*1024*1024/gi;
$s =~ s/Gi?/*1024*1024*1024/gi;
$s =~ s/Ti?/*1024*1024*1024*1024/gi;
$s =~ s/Pi?/*1024*1024*1024*1024*1024/gi;
$s =~ s/Ei?/*1024*1024*1024*1024*1024*1024/gi;
$s =~ s/Zi?/*1024*1024*1024*1024*1024*1024*1024/gi;
$s =~ s/Yi?/*1024*1024*1024*1024*1024*1024*1024*1024/gi;
$s =~ s/Xi?/*1024*1024*1024*1024*1024*1024*1024*1024*1024/gi;
$s = eval $s;
return $s;
}
sub get_options_from_array {
# Run GetOptions on @array
# Returns:
@ -109,6 +142,7 @@ sub get_options_from_array {
"factor|f=s" => \$::opt_factor,
"hard|H" => \$::opt_hard,
"soft|S" => \$::opt_soft,
"sensor=s" => \$::opt_sensor,
"si|sio|startio|start-io=s" => \$::opt_start_io,
"ri|rio|runio|run-io=s" => \$::opt_run_io,
@ -541,17 +575,82 @@ sub sleep_while_running {
}
# An non-blocking filehandle read that returns an array of lines read
# Returns: ($eof,@lines)
my %nonblockGetLines_last;
sub nonblockGetLines {
my ($fh,$timeout) = @_;
$timeout = 0 unless defined $timeout;
my $rfd = '';
$nonblockGetLines_last{$fh} = ''
unless defined $nonblockGetLines_last{$fh};
vec($rfd,fileno($fh),1) = 1;
return unless select($rfd, undef, undef, $timeout)>=0;
# I'm not sure the following is necessary?
return unless vec($rfd,fileno($fh),1);
my $buf = '';
my $n = sysread($fh,$buf,1024*1024);
my $eof = eof($fh);
# If we're done, make sure to send the last unfinished line
return ($eof,$nonblockGetLines_last{$fh}) unless $n;
# Prepend the last unfinished line
$buf = $nonblockGetLines_last{$fh}.$buf;
# And save any newly unfinished lines
$nonblockGetLines_last{$fh} =
(substr($buf,-1) !~ /[\r\n]/ && $buf =~ s/([^\r\n]*)$//)
? $1 : '';
$buf ? ($eof,split(/\n/,$buf)) : ($eof);
}
sub read_sensor {
my $self = shift;
my $fh = $self->{'sensor_fh'};
if(not $fh) {
# Start the sensor
open($fh, "-|", $::opt_sensor) || ::die_bug("Cannot open: $::opt_sensor");
$self->{'sensor_fh'} = $fh;
}
# Read as much as we can (non_block)
my ($eof,@lines) = nonblockGetLines($fh);
# new load = last full line
foreach my $line ( @lines ) {
if(defined $line) {
print "Pipe saw: $eof [$line]\n";
$Global::last_sensor_reading = $line;
}
}
if($eof) { undef($self->{'sensor_fh'}); }
return $Global::last_sensor_reading;
}
sub load_status {
# Returns:
# loadavg
# loadavg or sensor measurement
my $self = shift;
if($::opt_sensor) {
if(not defined $self->{'load_status'} or
$self->{'load_status_cache_time'} + $self->{'recheck'} < time) {
$self->{'load_status'} = $self->read_sensor();
while (not defined $self->{'load_status'}) {
sleep 1;
$self->{'load_status'} = $self->read_sensor();
}
$self->{'load_status_cache_time'} = time;
}
} else {
# Normal load avg
# Cache for some seconds
if(not defined $self->{'load_status'} or
$self->{'load_status_cache_time'}+$self->{'recheck'} < time) {
$self->{'load_status_cache_time'} + $self->{'recheck'} < time) {
$self->{'load_status'} = load_status_linux();
$self->{'load_status_cache_time'} = time;
}
::debug("load_status: $self->{'load_status'}\n");
}
::debug("load_status: ".$self->{'load_status'}."\n");
return $self->{'load_status'};
}

View file

@ -7,7 +7,8 @@ niceload - slow down a program when the load average is above a certain limit
=head1 SYNOPSIS
B<niceload> [-v] [-h] [-n nice] [-I io] [-L load] [-M mem] [-N]
[-t time] [-s time|-f factor] ( command | -p PID )
[--sensor program] [-t time] [-s time|-f factor] ( command | -p PID )
=head1 DESCRIPTION
@ -131,6 +132,19 @@ Run limit. The running program will be slowed down if the system is
above the limit. See: B<--io>, B<--load>, B<--mem>, B<--noswap>.
=item B<--sensor> I<sensor program> (alpha testing)
Read sensor. Use I<sensor program> to read a sensor.
This will keep the CPU temperature below 80 deg C on GNU/Linux:
niceload -l 80000 -f 0.001 --sensor 'sort -n /sys/devices/platform/coretemp*/temp*_input' gzip *
This will stop if the disk space < 100000.
niceload -H -l -100000 --sensor "df . | awk '{ print \$4 }'" echo
=item B<--start-io> I<iolimit>
=item B<--si> I<iolimit>