UPD : manterei minha solução por causa do histórico, mas systemctl set-property
deve ser chamado no momento do login, usando pam_exec
, consulte link . Nesta abordagem, não há janela de tempo entre o login do usuário e a configuração de limites.
Solução antiga
Aqui está um script muito simples que faz o trabalho
#!/bin/bash
STATE=1 # 1 -- waiting for signal; 2 -- reading UID
dbus-monitor --system "interface=org.freedesktop.login1.Manager,member=UserNew" |
while read line
do
case $STATE in
1) [[ $line =~ member=UserNew ]] && STATE=2 ;;
2) read dbus_type ID <<< $line
systemctl set-property user-$ID.slice CPUAccounting=true
STATE=1
;;
esac
done
Ele pode ser facilmente estendido para suportar limites de memória por usuário.
Testado em uma VM com 2 CPUs e 2 usuários. O primeiro usuário executa o comando dd if=/dev/zero of=/dev/null | dd if=/dev/zero of=/dev/null
e o segundo executa apenas uma instância de dd
. Sem esse script em execução, cada instância de dd
usava cerca de 70% da CPU.
Em seguida, iniciei o script, reutilizei os usuários e executei novamente dd
dos comandos. Desta vez, dois processos dd
do primeiro usuário receberam apenas 50% da CPU cada e o processo do segundo usuário levou 100% da CPU. Além disso, systemd-cgtop
mostrou que /user.slice/user-UID1.slice
e /user.slice/user-UID2.slice
tomam 100% do tempo de CPU cada, mas a primeira fatia tem 6 tarefas e a segunda apenas 5 tarefas.
Quando eu mato a tarefa dd
do segundo usuário, o primeiro usuário começa a consumir 200% do tempo da CPU. Portanto, temos uma alocação justa de recursos sem restrições artificiais, como "cada usuário pode usar apenas um núcleo".