Como eu restringiria um binário do Linux a uma quantidade limitada de RAM?

3

Eu gostaria de poder limitar um binário instalado para poder usar apenas uma certa quantidade de RAM. Eu não quero que ele seja morto se exceder, só que essa seria a quantidade máxima que ele poderia usar. Eu gostaria que o processo morresse quando atingisse uma certa quantidade de RAM, preferencialmente antes que o servidor comece a trocar muito.

O problema que estou enfrentando é que estou executando um servidor Apache 2.2 com PHP e algum código customizado que um desenvolvedor está escrevendo para nós. O problema é que em algum lugar lá código eles lançam uma chamada exec PHP que lança 'converter' do ImageMagick para criar um arquivo de imagem redimensionada.

Não estou familiarizado com muitos detalhes do projeto ou do código, mas preciso encontrar uma solução para evitar que eles matem o servidor até que possam encontrar uma maneira de otimizar o código.

Eu pensei que poderia fazer isso com o /etc/security/limits.conf e definir um limite para o usuário do apache, mas parece não ter efeito. Isso é o que eu usei:

www-data hard como 500

Se eu entendi corretamente, isso deve ter limitado qualquer processo de usuário do apache a um máximo de 500kb, no entanto, quando eu corri um script de teste que consumia muita memória RAM, ele chegou a 1.5GB antes de eu matar isto. Aqui está a saída de 'ps auxf' após a mudança de configuração e uma reinicialização do sistema:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root      5268  0.0  0.0 401072 10264 ?        Ss   15:28   0:00 /usr/sbin/apache2 -k start
www-data  5274  0.0  0.0 402468  9484 ?        S    15:28   0:00  \_ /usr/sbin/apache2 -k start
www-data  5285  102  9.4 1633500 1503452 ?     Rl   15:29   0:58  |   \_ /usr/bin/convert ../tours/28786/.….
www-data  5275  0.0  0.0 401072  5812 ?        S    15:28   0:00  \_ /usr/sbin/apache2 -k start

Em seguida, achei que poderia fazer isso com a configuração RlimitMEM do Apache, mas consegui que o mesmo resultado não ficasse limitado. Aqui está o que eu tenho no meu arquivo apache.conf:

RLimitMEM 500000 512000

Não foi até muitas horas depois que percebi que, se o processo realmente atingisse esse valor, ele morreria com um erro OOM.

Adoraria ideias sobre como definir esse limite para que outras coisas funcionassem no servidor, e todas elas poderiam funcionar juntas bem.

    
por Ken S. 01.10.2012 / 23:05

4 respostas

3

Crie um novo usuário, apenas para o ImageMagick. Dê os limites de memória que você deseja. Configure o arquivo sudoers de uma forma que o Apache possa chamar o ImageMagick como esse usuário. Altere a chamada exec () em seu código PHP para executar a conversão via sudo ou substitua o binário original convertido por um script wrapper. Se o ImageMagick estiver comendo toda a memória, deixe-o morrer e deixe o script PHP lançar uma mensagem de erro apropriada.

Ou substitua o ImageMagick todos juntos, é um grande merecido de memória (tente juntar blocos de pequenas figuras juntos. Em um ponto você se lembrará por que ainda está tendo uma partição swap).

    
por 02.10.2012 / 08:56
3

Existe uma nova interface do kernel (2.6.24) chamada cgroups que permite fazer isso. Você pode colocar um usuário, grupo ou PID (com filhos) sob um cgroup, e dar a ele uma quantidade X de RAM, CPU, IO (disco, rede) etc. É bastante limpo e extremamente poderoso quando usado com máquinas virtuais KVM. Veja wikipedia e o documentos oficiais para mais informações.

    
por 02.10.2012 / 20:42
1

A resposta simples é: você não pode. Se o programa não puder alocar mais memória, irá falhar. Você pode manter a memória do servidor em certas bordas configurando os trabalhadores e tudo, mas isso limitará o desempenho.

Se você precisar de mais oxigênio e não tiver mais, também morrerá. Não há outro resultado.

    
por 02.10.2012 / 00:52
0

Se a opção Rlimitmeme não deu certo, parece haver poucas chances de chegar ao limite. Você pode me mostrar os rastreamentos da pilha matadora da OOM em uma pasta, pelo menos, para que eu possa ver quais zonas estão se esgotando ou como a alocação está falhando. Não é uma solução para o problema que você tem, mas uma depuração mais comum que eu prefiro fazer.

No entanto, eu realmente não penso em uma maneira de limitar um binário para usar uma certa quantidade de RAM. Isso é dificilmente possível, eu acho.

    
por 02.10.2012 / 02:30