Digamos que eu tenho 20 usuários conectados na minha caixa Linux. Como posso saber quanta memória cada um deles está usando?
Digamos que eu tenho 20 usuários conectados na minha caixa Linux. Como posso saber quanta memória cada um deles está usando?
Respostas:
Você pode tentar usar o smem (consulte ELC2009: Visualizando o Uso da Memória com o Smem para obter mais informações). Em particular, sudo smem -u
deve fornecer as informações que você deseja.
--no-install-recommends
.
Ignorando problemas de memória compartilhada, aqui está um script rápido que fornece RSS e VMEM para todos os usuários conectados, classificados por vmem e organizados em colunas atraentes:
(echo "user rss(KiB) vmem(KiB)";
for user in $(users | tr ' ' '\n' | sort -u); do
echo $user $(ps -U $user --no-headers -o rss,vsz \
| awk '{rss+=$1; vmem+=$2} END{print rss" "vmem}')
done | sort -k3
) | column -t
Para obter a soma do RSS, acho que o seguinte funciona. Seria obter a soma do RSS para os usuários kbrandt e root.
ps -U kbrandt,root --no-headers -o rss | (tr '\n' +; echo 0) | bc
Essa é uma pergunta complicada. Você poderia facilmente resumir os valores totais de troca de RSS + na saída "ps", mas e a memória compartilhada? Usuários diferentes podem compartilhar facilmente a mesma página de código se estiverem executando o mesmo processo. Para quem você considera isso? E os buffers e cache? Realmente depende da precisão que você deseja que seus resultados sejam. Quanto mais preciso você quiser, mais difícil será.
Não tenho certeza de como relatar o uso de memória pelo usuário, mas se você estiver preocupado em controlar o uso deles, deve procurar ulimit. Isso permitirá que você defina limites rígidos e flexíveis por usuário / grupo para memória e outros recursos em seu sistema.
Você pode tentar algo como:
ps auxU maxwell | awk '{memória + = $ 4}; END {print memory} '
ps aux | grep mysql | awk '{memory +=$4}; END {print memory }'
, onde o mysql poderia ser substituído pelo nome de um usuário ou processo.
Procurando o mesmo, descobri isso
ps aux | awk '{arr[$1]+=$4}; END {for (i in arr) {print i,arr[i]}}' | sort -k2
para imprimir processos ordenados por mem, agrupados por usuário (coluna1, $ 1), você pode agrupar por outras coisas e somar outras, alterando $ 1 e $ 4
Fiquei feliz em encontrar a solução, só queria compartilhar.
ps --no-headers -eo user,rss | awk '{arr[$1]+=$2}; END {for (i in arr) {print i,arr[i]}}' | sort -nk2
. O comando de classificação precisa do -n
sinalizador para analisar a memória como um número. Dessa forma, você também pode substituir a palavra "usuário" por "comando" para agrupar pelo nome do aplicativo.
Esse script do bash provavelmente é feio como o inferno, mas obrigado pelo exercício, meu bash estava (está) ficando enferrujado!
#!/bin/sh
OLDIFS=$IFS
IFS=$'\n'
tempsum=0
totalmem=0
for m in `ps -eo user,rss --sort user | sed -e 's/ */ /g' | awk -F'[ ]' {'print $0'}`; do
nu=`echo $m|cut -d" " -f1`
nm=`echo $m|cut -d" " -f2`
# echo "$nu $nm $nu"
if [ "$nu" != "$ou" ] && [ $(echo "$nm"|grep -E "^[0-9]+$") ]
then
if [ "$tempsum" -ne 0 ]; then echo "Printing total mem for $ou: $tempsum"; fi
ou=$nu
tempsum=$nm
let "totalmem += $nm"
else
let "tempsum += $nm"
let "totalmem += $nm"
fi
done
echo "Total Memory in Use: $totalmem/$(free | grep Mem: | awk '{print $2}')"
IFS=$OLDIFS
Resultado:
[20:34][root@server2:~]$ ./memorybyuser.sh
Printing total mem for admin: 1387288
Printing total mem for apache: 227792
Printing total mem for avahi: 1788
Printing total mem for dbus: 980
Printing total mem for 68: 3892
Printing total mem for root: 55880
Printing total mem for rpc: 292
Printing total mem for rpcuser: 740
Printing total mem for smmsp: 720
Printing total mem for xfs: 680
Total Memory in Use: 1682360/4152144
Comente / corrija e atualizarei a resposta. Também uso a saída de memória rss do PS, como outros discutiram, há prós / contras no uso desse valor.
O smem não estava disponível no meu sistema, e o script de Dave não funcionou por algum motivo, então escrevi este feio onliner do Perl para processar a saída do ps:
ps -eo user,rss | perl -e 'foreach (<>) { m/(\w+)\s+(\d+)/; $mem{$1} += $2; }; foreach $u (keys %mem) { if ($mem{$u}) { print "$u - $mem{$u}\n" }}' | sort
Observe que alguns usuários foram identificados usando o UID em vez do nome de usuário. Você pode lidar com isso analisando nomes de usuários em / etc / passwd, usando o mais feio:
ps -eo user,rss | perl -e 'open(F, "/etc/passwd"); foreach $l (<F>) { if ($l=~/(.*?):.*?:(\d+)/) { $users{$2}=$1; }}; foreach (<>) { m/(\w+)\s+(\d+)/; $mem{$1} += $2; }; foreach $u (keys (%mem)) { $UN = $u; if ($UN=~/^\d+$/) { $UN = $users{$UN};}; if ($mem{$u}) { print "$UN - $mem{$u}\n" }}' | sort
Usando script Bash
#!/bin/bash
total_mem=0
printf "%-10s%-10s\n" User MemUsage'(%)'
while read u m
do
[[ $old_user != $u ]] && { printf "%-10s%-0.1f\n" $old_user $total_mem;
total_mem=0; }
total_mem="$(echo $m + $total_mem | bc)"
old_user=$u
done < <(ps --no-headers -eo user,%mem| sort -k1)
#EOF
SAÍDA
User MemUsage(%)
apache 4.8
dbus 0.0
mysql 3.8
nagios 3.1
Bem, neste estado do kernel Linux, posso pensar em apenas uma maneira adequada de realizar essa tarefa - usando cgroups de memória. Você precisaria colocar um usuário no login no próprio cgroup, e isso pode exigir o desenvolvimento do próprio módulo pam ou (melhor) modificar o módulo existente para isso.
Um documento útil para ler sobre isso é: Guia de Gerenciamento de Recursos da RedHat®.