Os artigos mais lidos

Quarta, Janeiro 30, 2013 Helio Loureiro Blog 18816
XGH é uma das coisas mais genias que surgiu nos últimos tempos, descrevendo a estupidez que se aplica em métodos ágeis, mas que reflete bem o ambiente corporativo. Infelizmente o site foi abandonado...
Sábado, Maio 03, 2008 Helio Loureiro FreeBSD 15909
This article is kindly linked by: http://tuxmobil.org/hp_compaq.html http://tuxmobil.org/mobile_bsd.html Barely finished my last article about FreeBSD (PRERELEASE at that time) on Compaq laptops,...
Quarta, Junho 11, 2014 Helio Loureiro Blog 15779
Nem só de discussões de licença, flamewares, releases de kernel e ativistas sapatênis vive o mundo do software livre. Às vezes é envolto de mistério também. Um dos enigmas recentes foi o sumiço da...
Sexta, Maio 20, 2005 Helio Loureiro Python 15501
Esse é o script usado para autenticar automaticamente no Speedy da Telefonica (região de São Paulo). Evita que usuários residenciais, como eu, precisem estar em frente à máquina, permitindo que a...

O calcanhar de Aquiles do Linux sempre foi o gerenciamento de memória.  Por mais memória que se tenha disponível, ele vorazmente sempre quer mais.  E nunca libera a memória livre.

E meus parcos 6 GB de memória do laptop tem sentido isso nesses últimos dias de 2012.   E verificável pelos gráficos do Munin, que mostra o pedido de 10 GB de memória pra usar.  Isso me faz pensar que talvez os Maias esteja certos.

 

 

Eu ainda não descobri qual programa (ou processo) está causando isso, e o kernel Linux não cuida de matar o processo comilão.

Então criei um pequeno daemon, em perl, para ficar lendo o /proc e matando os processos que mais consomem memória se a carga do sistema aumentar muito (atualmente marquei para load average maior de 10).

 

#! /usr/bin/perl

use POSIX;

$PROC = "/proc";
$MAXLOAD = 10;  #loadaverage
$SLEEPTIME = 1; #seconds

if (getuid() != 0) {
  print "Only root can run this program.\n";
  exit(1);
}

if (! -d $PROC) {
  print "Not possible to run.  System not running with $PROC directory\n";
  exit(1);
}

sub GetMem() {
  $pid_dir = $_[0];
  my $dir = $PROC."/".$pid_dir."/statm";
  open(MEM, $dir) or die "Error:$dir $!\n";
  @params = split(/ /, );
  close MEM;
  $memory = $params[0];

  return $memory;
}

sub GetPID() {
  my %MEM;
  opendir(PROC,$PROC) or die "Not possible to run.  System not running with $PROC directory\n";

  foreach $dir (readdir PROC) {
	# Just read higher processes
	# avoid init (1) or non-pid
	next if ($dir !~ m/^\d\d\d+/);
	$mem = &GetMem($dir);
	if ($mem) {
	  $MEM{$dir} = $mem;
	}
	
  }
  closedir PROC;

  return %MEM;
}

sub GetLoad() {
  open(LOAD,$PROC."/loadavg") or die "Impossible to detect load average by $PROC:$!\n";
  my $load = ;
  close LOAD;
  my @params = split(/ /, $load);

  return $params[0];
}

sub GetCommand() {
  my $pid = $_[0];
  open(CMD, $PROC."/".$pid."/cmdline") or die "Impossible to read the source command: $!\n";
  my $cmd = ;
  close CMD;

  return $cmd;
}

sub DaemonizeMe() {
  print "Starting to memory control daemon\n";
  POSIX::setsid or die "setsid: $!";
  my $pid = fork ();
  if ($pid < 0) {
	die "fork: $!";
  } elsif ($pid) {
	exit 0;
  }
  chdir "/";
  umask 0;
  foreach (0 .. (POSIX::sysconf (&POSIX::_SC_OPEN_MAX) || 1024)) { 
	POSIX::close $_; 
  }
  open (STDIN, "/dev/null");
  #open (STDERR, ">&STDOUT");
}

&DaemonizeMe();
my $mypid = getpid();
my %DEATHCOUNTER;

while (! $SIG{TERM}) {
  
  sleep($SLEEPTIME);
  my $load = &GetLoad();
  next if ($load < $MAXLOAD);
  my %MEM;
  %MEM = &GetPID();

  $higher_m = 0;
  $higher_pid = 0;

  foreach $k (sort keys %MEM) {
	next if ($k eq $mypid);
	$mem = $MEM{$k};
	if ($mem > $higher_m) {
	  $higher_m = $mem;
	  $higher_pid = $k;
	  $DEATHCOUNTER{$higher_pid}++;
	}
  }

  if ($DEATHCOUNTER{$higher_pid} >= 5) {
	print "Killing due higher memory usage: ".&GetCommand($higher_pid)." (".$higher_pid.") [".$higher_m." Bytes]\n";
	%DEATHCOUNTER;
  }
}

print "Exiting...";
exit(0);

Os Maias podiam até estar certos, mas isso não significa que precisamos ficar sentados olhando.