Limitar os processos a não exceder mais de 10% do uso da CPU

32

Eu opero um sistema Linux que possui muitos usuários, mas às vezes ocorre um abuso; onde um usuário pode executar um único processo que consome mais de 80% da CPU / Memória.

Portanto, existe uma maneira de impedir que isso aconteça, limitando a quantidade de uso da CPU que um processo pode usar (para 10%, por exemplo)? Estou ciente cpulimit, mas infelizmente aplica o limite aos processos que eu o instruo a limitar (por exemplo, processos únicos). Portanto, minha pergunta é: como posso aplicar o limite a todos os processos em execução e processos que serão executados no futuro sem a necessidade de fornecer seu ID / caminho, por exemplo?

Giovanni Mounir
fonte
Você está tendo problemas de desempenho? ou são apenas os números que o incomodam?
ctrl-alt-delor
@richard Problemas de desempenho, é por isso que eu estava tentando matar / limitar / encerrar processos que parecem estar usando muita CPU, mas já o fiz escrevendo um script bash. Esta é também uma máquina virtual se isso ajuda
Giovanni Mounir
2
Cuidado para eliminar processos que podem ser 100% por muito pouco tempo, também processos do sistema. Considere cpulimitem conjunto com seu script de pesquisa. Tenha uma política e recomende o uso de cpulimit, procure por mais de 10% e depois limite a 5% (para que os usuários sejam incentivados a usar cpulimit). Além disso, verifique se você pode detectar vários processos, somando mais de 10% para um único usuário.
Ctrl-alt-delor
@richard Obrigado Richard por todos esses comentários bastante úteis! Eles me ajudaram muito! Sua sugestão de uso cpulimité muito melhor do que apenas matar o processo, pois ele pode ser reiniciado pelo usuário mais tarde (conforme indicado em um de seus comentários). Obrigado!
Giovanni Mounir
1
stackoverflow.com/questions/386945/…
Ciro Santilli escreveu:

Respostas:

20

Embora possa ser um abuso de memória, não é para a CPU: quando uma CPU está ociosa, um processo em execução (por "execução", quero dizer que o processo não está esperando por E / S ou outra coisa) será necessário. 100% de tempo da CPU por padrão. E não há razão para impor um limite.

Agora, você pode definir prioridades graças a nice. Se você deseja que eles se apliquem a todos os processos para um determinado usuário, você só precisa garantir que o shell de logon seja executado com nice: os processos filhos herdarão o nicevalor. Isso depende de como os usuários efetuam login. Consulte Priorizar logins ssh (simpáticos), por exemplo.

Como alternativa, você pode configurar máquinas virtuais. De fato, definir um limite por processo não faz muito sentido, pois o usuário pode iniciar muitos processos, abusando do sistema. Com uma máquina virtual, todos os limites serão globais para a máquina virtual.

Outra solução é estabelecer /etc/security/limits.conflimites; consulte a página do manual limits.conf (5). Por exemplo, você pode definir o tempo máximo da CPU por login e / ou o número máximo de processos por login. Você também pode definir maxlogins1 para cada usuário.

vinc17
fonte
1
@GiovanniMounir eu quis dizer: uma máquina virtual por usuário.
precisa saber é
1
Entendo, mas infelizmente isso consumirá recursos e não será realmente útil para meus propósitos, pois os usuários podem exigir o uso de alguns pacotes de desenvolvimento comuns e não instalarei isso em todas as máquinas novas; Eu acho que é melhor deixar dessa maneira e fazer o monitoramento automaticamente por um script bash.
Giovanni Mounir
1
@GiovanniMounir Você pode compartilhar uma partição entre várias máquinas virtuais.
precisa saber é
@GiovanniMounir Você pode usar o LXC ou o Docker para diminuir a sobrecarga da virtualização para quase zero. Também "gostar" não é um motivo forte. Por exemplo, eu usaria sua solução se você estiver gerenciando um host PHP compartilhado, porque fazer LXCs ou Máquinas Virtuais exigirá a reescrita de um software licenciado de US $ 15 / US $ 5 que é um exagero.
Pooyan Khosravi
meu entendimento é que nice apenas define a CPU relativa em comparação com outros processos. Se nenhum outro processo estiver usando CPU, seu processo usará 100% da CPU, não limitando a 10%.
johny why
25

nice / renice

nice é uma ótima ferramenta para ajustes únicos em um sistema.

 nice COMMAND

cpulimit

cpulimit se você precisar executar um trabalho intensivo da CPU e ter tempo livre da CPU é essencial para a capacidade de resposta de um sistema.

cpulimit -l 50 COMMAND

cgroups

cgroups aplicar limites a um conjunto de processos, em vez de apenas um

cgcreate -g cpu:/cpulimited
cgset -r cpu.shares=512 cpulimited
cgexec -g cpu:cpulimited COMMAND_1
cgexec -g cpu:cpulimited COMMAND_2
cgexec -g cpu:cpulimited COMMAND_3

Recursos

http://blog.scoutapp.com/articles/2014/11/04/restricting-process-cpu-usage-using-nice-cpulimit-and-cgroups

RafaSashi
fonte
5
Para aqueles que procuram definir um limite rígido sobre o uso da CPU, mesmo quando nenhum outro processo está em execução, olhada cpu.cfs_quota_usde parâmetros (ver o manual )
Diego
cgroups são mais fáceis de usar, graças às directivas Systemd ... criar um qualquer sistema unidade ou usuário para o efeito é a melhor opção
Yves Martin
para um processo em execução ex .:sudo cgclassify -g cpu:cpulimited 2315444
Aquarius Power
1
meu entendimento é que nice apenas define a CPU relativa em comparação com outros processos. Se nenhum outro processo estiver usando CPU, seu processo usará 100% da CPU, não limitando a 10%.
johny why
10

Você olhou para os cgroups? Há alguma informação no Arch Wiki sobre eles. Leia a seção sobre cpu.shares, parece que está fazendo o que você precisa, e eles podem operar no nível do usuário, para que você possa limitar todos os processos do usuário de uma só vez.

Paul Schyska
fonte
CGroups é o caminho a percorrer, no entanto. Também executo (muitos) servidores de computador compartilhados e usamos o cgroups para limitar o número máximo de núcleos que uma sessão de login inteira pode usar. Dessa forma, se a pessoa continua iniciando novos processos, cada um recebe uma fatia menor. O mesmo para uso em memória. Você pode colocar os usuários automaticamente em um cgroup com pam_cgroups e o serviço cgrulesengd. Você pode usar um 'modelo' no arquivo cgconfig para colocar cada usuário em seu próprio cgroup. O cgrulesengd age como seu script, exceto que, em vez de interromper os processos, apenas garante que cada processo esteja no cgroup certo.
Jsbillings
Mesmo se você não usar o cgroups para limitar o uso de recursos, poderá usá-lo para avaliar a quantidade de recursos que um indivíduo está usando, observando o arquivo 'stat' de cada recurso e, em seguida, use essas informações para o seu script de 5 minutos.
Jsbillings
3

Para memória, o que você está procurando é ulimit -v. Observe queulimit é herdado por processos filho; portanto, se você o aplicar ao shell de login do usuário no momento do login, ele se aplicará a todos os seus processos.

Se todos os usuários usarem bashcomo shell de logon, colocar a linha a seguir /etc/profiledeve fazer com que todos os processos do usuário tenham um limite rígido de 1 gigabyte (mais exatamente, um milhão de kilobytes):

ulimit -vH 1000000

A opção H garante um limite rígido, ou seja, o usuário não pode configurá-lo novamente depois. Obviamente, o usuário ainda pode preencher memória iniciando processos suficientes ao mesmo tempo.

Para outros shells, você precisará descobrir quais arquivos de inicialização eles lêem (e qual outro comando, em vez de ulimitusar).

Para CPU, o que você deseja não parece fazer sentido para mim. Qual seria a utilidade de deixar 90% da CPU não ser utilizada quando apenas um processo estiver em execução? Eu acho que o que você realmente quer é nice(e possivelmente ionice). Observe que, assim ulimit, os nicevalores são herdados pelos processos filhos, portanto, aplicá-lo ao shell de login no momento do login é suficiente. Eu acho que isso também se aplica, ionicemas não tenho certeza.

celtschk
fonte
Obrigado pela sugestão de memória! Existe alguma chance de você me mostrar um exemplo para aplicar isso ao shell de login do usuário no momento do login? Não tenho muita certeza de como fazer isso. Também sinto muito por não ser suficientemente claro; o que estou tentando fazer é não permitir que nenhum processo use mais de 10% da CPU. Então você acha que niceisso será bom o suficiente para fazer isso? Se sim, você acha que pode me mostrar um exemplo para conseguir isso?
Giovanni Mounir
Ainda não entendo o motivo de manter a CPU 90% ociosa quando apenas um processo está em execução.
Celtschk
1
Se atualmente houver menos de 10 processos em execução simultaneamente (e executando, quero dizer realmente em execução, não apenas aguardando entrada do usuário ou E / S de disco), é praticamente garantido que um deles terá mais de 10% da CPU. Caso contrário, a CPU estaria praticamente ociosa. E se você simplesmente matar qualquer processo acima de 10%, tenho certeza de que terá muitos usuários que desejarão matá- lo. Ou pelo menos, tentará substituí-lo por alguém que tenha uma idéia do que esses números significam, porque você não parece.
Celtschk
Ao contrário do comentário de @celtschk, se houver 11 ou mais processos em execução (vinculado à CPU), eles serão inferiores a 9,09%. Portanto, se eu sou usuário de um sistema que proíbe mais de 10% de uso da CPU, posso executar 11 ou mais processos e me esconder sob o radar.
Ctrl-alt-delor
@richard Você está certo, talvez seja melhor se o script resumir a quantidade total de memória / CPU usada por um usuário e finalizar todos os processos desse usuário quando a porcentagem atingir uma quantidade específica (também o registrará )
Giovanni Mounir
3

Como você está afirmando que o cpulimit não seria prático no seu caso, sugiro que você analise nice , renice e tasket , que podem se aproximar do que você deseja alcançar, embora o tasket permita definir a afinidade da CPU de um processo, por isso pode não ser útil imediatamente no seu caso.

RJ
fonte
1
nicee renice? Isso é bom! Examinei as páginas de manual, mas ainda não acho que elas possam ajudar com isso, pois você ainda precisa definir um ID do processo. Se você pudesse, no entanto, me dar um exemplo que envolva esses pacotes para aplicar o limite em todos os processos em execução / processos futuros que seriam incríveis!
Giovanni Mounir
1

Como suas tags possuem centos, você pode usar systemd.

Por exemplo, se você deseja limitar o usuário com o ID de 1234:

sudo systemctl edit --force user-1234.slice

Em seguida, digite e salve este:

[Slice] CPUQuota=10%

Na próxima vez em que o usuário fizer login, isso afetará.

Páginas man: systemctl, systemd.slice, systemd.resource-control...

pilha-políticas-são-trolls
fonte
0

Se você deseja limitar os processos que já foram iniciados, precisará fazê-lo um a um pelo PID, mas pode ter um script em lote para fazer isso como o abaixo:

#!/bin/bash
LIMIT_PIDS=$(pgrep tesseract)   # PIDs in queue replace tesseract with your name
echo $LIMIT_PIDS
for i in $LIMIT_PIDS
do
    cpulimit -p $i -l 10 -z &   # to 10 percent processes
done

No meu caso pypdfocrlança o ganancioso tesseract.

Além disso, em alguns casos, sua CPU é muito boa e você pode usar um exemplo renicecomo este:

watch -n5 'pidof tesseract | xargs -L1 sudo renice +19'
Eduard Florinescu
fonte