Por que meu script está lentamente usando mais e mais memória? É por causa do midori?

1

Eu fiz um script para exibir vários sites em um loop infinito e percebi que o sistema está lentamente consumindo mais e mais memória. O script funciona perfeitamente de outra forma.

Pelo que consegui reunir do comando top , acredito que seja midori (o navegador da internet) que está consumindo todos (bem, pelo menos uma grande porcentagem) da memória. Meu midori está configurado para abrir todas as páginas na guia atual, portanto, há apenas uma instância de midori em execução e apenas uma guia aberta, mas ainda continua a aumentar o uso da memória.

#Start VNC Server
x11vnc -display :0 -usepw -listen ip_addr &

#Sites to display
SITES=( "a bunch of urls here..." )
#Display Time (In Seconds)
TIME=( 125 35 35 35 35 35 20 20 20 20 20 20 20 20 20 30 )


#Open the browser and enter fullscreen mode
midori http://google.com &
sleep 15
xdotool key F11

#Infinite Loop
while [ 1 -eq 1 ]; do

#Loop through each site
for ((i=0;i<${#SITES[@]};++i)); do
        #Open the site
        midori ${SITES[i]} &

        #Check to see if the site has a display time set in the TIME variable
        if [ -z ${TIME[i]} ];
        then #If the display time is not set, display for 30 seconds
                sleep 30
        else #Display for the appropriate amount of time
                sleep ${TIME[i]}
        fi
done
done

Alguma ideia? Obrigado.


Editar:
Vale a pena mencionar que, quando digo que está 'lentamente' usando mais memória, quero dizer muito devagar; depois de executar o script por ~ 7 horas, o consumo de memória passou de 35% - 61%.

    
por user183143 04.08.2016 / 21:04

1 resposta

2

Os navegadores da Web são notórios porcos de memória e vazadores de memória, especialmente se as páginas que estão visualizando tiverem algum javascript. É apenas parte da natureza deles. Além de talvez os navegadores em modo texto como lynx , eu acho que nunca vi um que não vazasse memória ao longo do tempo.

Você precisa que o navegador permaneça na tela depois que a última guia for exibida? Se não, então pkill midori entre as duas linhas done . Se você fizer isso, então pkill midori ; midori ${SITES[i]} & . Ou, no for loop: [ "$i" == "${#SITES[@]}" ] && pkill midori imediatamente antes de executar midori . ou loop de 0 a $ (("$ {# SITES [@]" - 1)), depois matando e iniciando o midori final após o primeiro done .

Ou, provavelmente, o mais simples, apenas pkill midori imediatamente após a instrução while (se o midori não estiver em execução, nenhuma mensagem de erro será impressa e nada acontecerá, a menos que você esteja executando com set -e ).

Se você não tiver o pkill instalado (ele está no pacote procps no debian e raspbian), você pode capturar o PID do processo midori sempre que ele for eliminado e reiniciado e eliminar esse PID específico. por exemplo,

while [ 1 ]; do
  mPID=0

  for ((i=0;i<"${#SITES[@]}";++i)); do
    midori "${SITES[i]}" &
    [ "$mPID" -eq 0 ] && [ -n "$(jobs -n)" ] && mPID=$!
    [ "$mPID" -eq 0 ] && echo "couldn't start midori" && exit 1

    # sleep for for display time if set, otherwise 30 secs.
    [ -n "${TIME[i]}" ] && sleep "${TIME[i]}" || sleep 30
  done
  kill "$mPID"
done

Isso não só faz com que o PID de qualquer novo processo midori seja iniciado ( $! é o PID do trabalho em segundo plano mais recente), ele verifica se ele foi iniciado. Se o midori não for executado por algum motivo, ele será encerrado com uma mensagem de erro.

Se você não estivesse rodando em um rpi, você poderia adicionar mais RAM ao seu sistema, se é que isso é possível. É uma maneira razoavelmente barata de melhorar o desempenho e a capacidade de resposta de um sistema, e qualquer RAM "não usada" será usada pelo kernel para armazenar seus discos em cache.

Eu escrevi um script que você pode achar útil, chamado mem-pigs.sh para totalizar o uso de memória para programas especificados. padrão para os navegadores que eu uso rotineiramente (porque eles são os porcos de memória).

#! /bin/bash

# print total RSS memory usage for program(s) with multiple pids

# set default if no args
[ -z "$1" ] && set -- chromium firefox midori

for p in "$@" ; do
  printf "%s:\t%s %s\n" "$p" $( 
    ( printf '1024*(%s)\n' \
        $(awk '
               BEGIN {if (ARGC==1) { print 0 ; exit } };
               /VmRSS:/ {print $2}
              ' \
            $(pgrep "$p" | sed -e 's:^:/proc/:;s:$:/status:') | 
          paste -sd+)
    ) | 
      bc | 
      human-numbers.pl)
done

exemplo de saída:

$ mem-pigs.sh
chromium:   9.81 GiB
firefox:    1.39 GiB
midori: 2.76 GiB

midori provavelmente usaria mais se eu o usasse como um navegador de uso geral, mas eu o utilizo apenas para o facebook e nada mais. cromo e firefox para navegação aleatória em coisas que me interessam.

chromium é o verdadeiro porco. está usando apenas 10 GB no momento, mas isso é porque eu reiniciei algumas horas atrás por causa de uma atualização (era cerca de 14 GB antes disso). mesmo para firefox , geralmente é em torno de 4-6GB. Mas eu deixo os dois correndo por semanas ou meses de cada vez com uma dúzia ou três guias por janela em 20 ou mais janelas cada. cada janela sendo principalmente sobre um tópico particular que eu estou lendo.

Eu fiquei meio horrorizado ao ver o quanto de cromo em particular estava sendo usado ... então eu pensei "dobrar minha memória RAM para 32 GB é de apenas US $ 100". agora eu realmente não me importo. Eu teria atualizado para 64GB se minha placa-mãe fosse DDR4 ou se DIMMs DDR3 de 32GB não fossem caros demais.

mem-pigs.sh usa outro script, human-numbers.pl :

#! /usr/bin/perl

use strict;
use warnings;

my $units = 1024;
my @suffixes=map { $_ ne 'B' && $_ } qw(B KiB MiB GiB TiB PiB EiB ZiB YiB);

if ( (@ARGV) && (($ARGV[0] eq '--si') || ($ARGV[0] eq '-s' )) ) {
  shift;
  $units = 1000;
  @suffixes=map { $_ ne 'B' && $_ } qw(B KB MB GB TB PB EB ZB YB);
};

# Use stdin and/or command-line args as input
# NOTE: command-line args are processed AFTER lines from stdin)
# TODO: option to process args BEFORE STDIN.
my @input = @ARGV;
@ARGV=();

if ( -p STDIN ) {
  while (<>) {
    push @input, $_;
  };
};

my $index=0;

for (@input) {
   my $n = $_ ;
   my $index = 0;

   for (@suffixes) {
     last  if $n < $units ;
     $n = $n / $units;
     $index++
   };

   printf "%.2f %s\n", $n, $suffixes[$index];
}
    
por 05.08.2016 / 18:37