Mate automaticamente um processo se exceder uma determinada quantidade de RAM

12

Eu trabalho em conjuntos de dados em larga escala. Ao testar um novo software, às vezes um script me aparece, pega rapidamente toda a RAM disponível e inutiliza minha área de trabalho. Gostaria de definir um limite de RAM para um processo, para que, se exceder esse valor, ele será eliminado automaticamente. Uma solução específica de idioma provavelmente não funcionará, pois eu uso todos os tipos de ferramentas diferentes (R, Perl, Python, Bash, etc.).

Portanto, existe algum tipo de monitor de processo que me permita definir uma quantidade limite de RAM e interromper automaticamente um processo se ele usar mais?

chrisamiller
fonte
@ Uri: Nesse tópico, recebi apenas uma resposta parcial (apenas para a parte da cpu da minha pergunta) - e não ótima -. Ele pergunta sobre o uso da RAM.
27411 Chriskin
1
Uri, há uma completa falta de idéias úteis nesse segmento. A publicação de um link para ele não é particularmente útil.
Chrisamiller
1
Hrmm - esta discussão superusuário parece ter uma sugestão razoável, usando ulimit: superuser.com/questions/66383/restrict-ram-for-user-or-process
chrisamiller

Respostas:

11

Detesto ser o cara que responde à sua própria pergunta, mas hoje de manhã encontrei um método alternativo, envolvido em uma pequena utilidade. Isso limitará o tempo da CPU ou o consumo de memória:

https://github.com/pshved/timeout

Estou dando uma chance a este primeiro, mas voto positivo para Amey Jah pela resposta agradável. Vou verificar se este me falha.

chrisamiller
fonte
5
+1 Responder a sua própria pergunta está OK !
Tom Brossman
10

Eu recomendo fortemente que não faça isso . Conforme sugerido por @chrisamiller, a configuração de ulimit limitará a RAM disponível com o processo.

Mas ainda assim, se você estiver insistindo, siga este procedimento.

  1. Salve o seguinte script como killif.sh:

    #!/bin/sh
    
    if [ $# -ne 2 ];
    then
        echo "Invalid number of arguments"
        exit 0
    fi
    
    while true;
    do
        SIZE=$(pmap $1|grep total|grep -o "[0-9]*")
        SIZE=${SIZE%%K*}
        SIZEMB=$((SIZE/1024))
        echo "Process id =$1 Size = $SIZEMB MB"
        if [ $SIZEMB -gt $2 ]; then
            printf "SIZE has exceeded.\nKilling the process......"
            kill -9 "$1"
            echo "Killed the process"
            exit 0
        else
            echo "SIZE has not yet exceeding"
        fi
    
        sleep 10
    done
  2. Agora torne-o executável.

    chmod +x killif.sh
    
  3. Agora execute este script no terminal. Substitua PROCIDpela identificação do processo real e SIZEpelo tamanho em MB.

    ./killif.sh PROCID SIZE
    

    Por exemplo:

    ./killif.sh 132451 100
    

    Se SIZEfor 100, o processo será interrompido se o uso da RAM for superior a 100 MB.

Cuidado: você sabe o que está tentando fazer. O processo de matar não é uma boa ideia. Se esse processo tiver algum comando de desligamento ou parada, edite o script e substitua o kill -9comando por esse shutdowncomando.

Amey Jah
fonte
Gostaria de considerar colocar pouco sono lá, por exemplo, o sono 0,5 ...
Denwerko
@ George Edison Como você fez isso. Quando tentei colar, ele estava me dando um texto estranhamente formatado. Denwerko: Onde você gostaria de dormir? Já coloquei um sono de 10 segundos no loop while
Amey Jah
2
Obrigado pela solução, como observado abaixo, eu posso dar uma olhada. Por que todos os avisos terríveis sobre processos de morte? O software de gerenciamento de cluster (LSF, PBS, et al) faz isso o tempo todo quando um processo excede a quantidade de recursos solicitados, sem consequências terríveis. Concordo que essa não é uma boa solução para novos usuários que provavelmente a aplicarão incorretamente, mas nas circunstâncias certas, isso pode ser bastante útil.
Chrisamiller
@chrisamiller Eu coloquei um aviso para futuros leitores. No seu caso, você conhece as implicações, mas o futuro leitor desta publicação pode não estar ciente dessas implicações.
Amey Jah
2
Você pode explicar por que não fazer isso?
jterm
2

Experimente a prlimitferramenta, na util-linuxembalagem. Ele executa um programa com limites de recursos. Ele usa a prlimitchamada do sistema para configurar os limites, que são então aplicados exclusivamente pelo kernel.

Você pode configurar 16 limites, incluindo:

  • quantidade máxima de tempo de CPU em segundos
  • número máximo de processos do usuário
  • tamanho máximo do conjunto de residentes ("memória usada")
  • tamanho máximo que um processo pode travar na memória
  • tamanho da memória virtual
  • número máximo de arquivos abertos
  • número máximo de bloqueios de arquivo
  • número máximo de sinais pendentes
  • bytes máximos nas filas de mensagens POSIX
Bram Geron
fonte
0

Era grande demais para caber em um comentário. Modifiquei o script original de Amey para incluir um pgrep, portanto, em vez de precisar inserir manualmente a identificação do processo, você pode excluir apenas pelo nome. Por exemplo, ./killIf.sh chrome 4000mata qualquer processo de cromo que exceda 4 GB no uso de memória.

#!/bin/sh

# $1 is process name
# $2 is memory limit in MB

if [ $# -ne 2 ];
then
    echo "Invalid number of arguments"
    exit 0
fi

while true;
do
    pgrep "$1" | while read -r procId;
    do
        SIZE=$(pmap $procId | grep total | grep -o "[0-9]*")
        SIZE=${SIZE%%K*}
        SIZEMB=$((SIZE/1024))
        echo "Process id = $procId Size = $SIZEMB MB"
        if [ $SIZEMB -gt $2 ]; then
            printf "SIZE has exceeded.\nKilling the process......"
            kill -9 "$procId"
            echo "Killed the process"
            exit 0
        else
            echo "SIZE has not yet exceeding"
        fi
    done

    sleep 1
done

Cuidado para selecionar uma seqüência de caracteres grep estreita e um limite de memória grande o suficiente para não matar desnecessariamente processos não intencionais.

Gaurang Tandon
fonte