mirror of
https://git.savannah.gnu.org/git/parallel.git
synced 2024-11-22 14:07:55 +00:00
niceload: minimal --sensor support.
This commit is contained in:
parent
00a2b4d119
commit
ce02b6f794
113
src/niceload
113
src/niceload
|
@ -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_start_noswap) { $::opt_start_noswap = $::opt_noswap; }
|
||||||
if(not defined $::opt_run_noswap) { $::opt_run_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 $limit = Limit->new();
|
||||||
my $process = Process->new($::opt_nice,@ARGV);
|
my $process = Process->new($::opt_nice,@ARGV);
|
||||||
if($::opt_pid) {
|
if($::opt_pid) {
|
||||||
|
@ -89,6 +91,37 @@ while($process->is_alive()) {
|
||||||
|
|
||||||
exit($::exitstatus);
|
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 {
|
sub get_options_from_array {
|
||||||
# Run GetOptions on @array
|
# Run GetOptions on @array
|
||||||
# Returns:
|
# Returns:
|
||||||
|
@ -109,6 +142,7 @@ sub get_options_from_array {
|
||||||
"factor|f=s" => \$::opt_factor,
|
"factor|f=s" => \$::opt_factor,
|
||||||
"hard|H" => \$::opt_hard,
|
"hard|H" => \$::opt_hard,
|
||||||
"soft|S" => \$::opt_soft,
|
"soft|S" => \$::opt_soft,
|
||||||
|
"sensor=s" => \$::opt_sensor,
|
||||||
|
|
||||||
"si|sio|startio|start-io=s" => \$::opt_start_io,
|
"si|sio|startio|start-io=s" => \$::opt_start_io,
|
||||||
"ri|rio|runio|run-io=s" => \$::opt_run_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 {
|
sub load_status {
|
||||||
# Returns:
|
# Returns:
|
||||||
# loadavg
|
# loadavg or sensor measurement
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
# Cache for some seconds
|
if($::opt_sensor) {
|
||||||
if(not defined $self->{'load_status'} or
|
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'} = $self->read_sensor();
|
||||||
$self->{'load_status_cache_time'} = time;
|
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'} = 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'};
|
return $self->{'load_status'};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@ niceload - slow down a program when the load average is above a certain limit
|
||||||
=head1 SYNOPSIS
|
=head1 SYNOPSIS
|
||||||
|
|
||||||
B<niceload> [-v] [-h] [-n nice] [-I io] [-L load] [-M mem] [-N]
|
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
|
=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>.
|
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<--start-io> I<iolimit>
|
||||||
|
|
||||||
=item B<--si> I<iolimit>
|
=item B<--si> I<iolimit>
|
||||||
|
|
Loading…
Reference in a new issue