Site icon Consejos WEB

Limitar el uso de CPU para un proceso (cpulimit)

En ocasiones necesitamos limitar el uso de la CPU de nuestro equipo para determinados procesos porque llegan a consumir demasiados recursos, como por ejemplo, en el caso de BOINC cuando está procesando un modelo (climateprediction.net).

Para solucionar este problema, en Linux, disponemos de cpulimit que fija el %máximo de cpu que un ejecutable o proceso prodrá utilizar.

La dirección para descargar las fuentes es esta:

https://sourceforge.net/projects/cpulimit

Utilizando este comando, he realizado un pequeño script que se encarga de controlar procesos que utilicen un uso elevado de CPU, de forma que envía un mensaje antes de limitar el usuo de CPU para ese proceso.

Puede funcionar como “daemon”, y se puede fijar la frecuencia con que va a chequear los procesos que están corriendo en la máquina, asicomo, el límite máximo de uso de cpu a partir del cual salta la alarma y lo limita para ese proceso. Partiendo de este script se pueden hacer cosas un poquito más sofisticadas como tomar decisiones en función de la carga del servidor, limitar el uso de cpu de forma selectiva para determinados procesos, realizar renices, …


#!/usr/bin/perl -w
# Mario Izquierdo (mario@izquierdo.co.uk)
use POSIX qw(setsid); #Use the POSIX library for daemonize this script

#Uncomment the next line if you want to run this script as a daemon
#&daemonize

#Sendmail command
$sendMailCmd = "/usr/sbin/sendmail -t";

#cpulimit command (where cpulimit is installed)
$cpuLimitCmd = "/usr/sbin/cpulimit";

#Infomation for sending the email
$to = 'destionation@email'; #The destination email here

$from = 'sender@email'; #The sender email here
$subject = 'Alarma: uso anormal de CPU'; #Here goes the subject

#Constants
my $cpuLimit = 10; #Maximun cpu usage allowed
my $message;
my $cpulimit;

my $cpulimitproc = '';
my $pid;
my $text;
my $tmpVar;
my $finalMessage = '';

#Uncomment the following code if you run this script as a daemon
#while (1) {
# sleep(15); #Change to the frequency you wnat to check the processes

#}

checkProcesses(); #Comment this line if running as a daemon

#Function to check
sub checkProcesses {

#Read all process running calling ps command
@data = split(/\n/, qx{ps aux});

#The ps command output format is:
my $headinf = "USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND\n";

for (my $c = 0; $c < @data; $c++) {

@inf = split(/\s+/, $data[$c]);

#Catch the PID of the current cpulimit processes limited
$_ = $inf[10];
if (/cpulimit/i)

{
$cpulimitproc .= $inf[12].','; #We assume the pid is the 12 item
}

#Check for any process running over the maximun cpu limit set above
#If exists then set an alarm

if ($inf[2] gt $cpuLimit)
{
$message{$inf[1]} = "Se ha registrado una alarma. El uso de CPU ha sido"
. "superado para el proceso:\n";
$message{$inf[1]} .= $headinf.join("\t", @inf);

}
}

#Walk the cpulimit processes found: Don't launch more cpulimits if exists
$_ = $cpulimitproc;

while (($pid,$text) = each(%message))
{
$tmpVar = $pid.',';
if (/$tmpVar/)
{
$message{$pid} = ''; #Clear the message since is already set

}
else #Limit the cpu usage for this process and add to the email message
{
qx/$cpuLimitCmd." -p ".$pid." -l ".$cpuLimit/;
$finalMessage .= $message{$pid};

}
}

if ($finalMessage ne '') {
sendMail($finalMessage);
}

else
{
print "No alarms to send\n";
}
}

exit(0);

#Function for send the alarm by email
sub sendMail {

$message = $_[0];

# Open the email
open(MAIL, "|$sendMailCmd");

## Email header
print MAIL "To: $to\n";
print MAIL "From: $from\n";
print MAIL "Subject: $subject\n";

## Email body

print MAIL $message;

close(MAIL);

}

#Call this function if you want to run this script as a daemon
sub daemonize {
chdir '/' or die "Can't chdir to /: $!";

open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!";
open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!";
defined(my $pid = fork) or die "Can't fork: $!";
exit if $pid;

setsid or die "Can't start a new session: $!";
umask 0;
}

Exit mobile version