
Necesito verificar el tamaño que ocupa cada usuario en mi servidor Linux (todos los archivos de forma recursiva dentro de mi carpeta de datos).
Con el siguiente código puedo obtener todos mis archivos y sus usuarios, pero no sé cómo agruparlos y sumarlos después de eso.
#> find . -type f -ls | sort -k5
¿Alguien tiene una idea para resolver este problema?
Respuesta1
Con GNU find
:
find . -printf '%D+%i:%u:%b\n' | awk -F: '
!seen[$1]++ {du[$2] += $3}
END {for (user in du) printf "%20s: %lu\n", user, du[user] * 512}'
Eso informaría el uso del disco en bytes para cada usuario. Al igual que du
esto, tiene cuidado de no contar los enlaces físicos varias veces.
find
imprime el dispositivo+número de inodo ( %D+%i
) para cada archivo (para enlaces físicos al mismo archivo, serían idénticos), el nombre de usuario y el uso del disco en unidades de 512 bytes.
:
se utiliza como separador de campos, ya que los nombres de usuario normalmente no los contienen, ya que son el separador de campos en la base de datos del usuario (como /etc/passwd
o la salida de getent passwd
).
Esa lista se envía a awk
, donde actualizamos una du
matriz asociativa indexada en el nombre del usuario ( $2
el segundo campo) para cada uno de los archivos para los cuales el primer campo aún no ha sido seen
.
En END
, recorremos los elementos de la matriz asociativa para informar el uso acumulado del disco para cada usuario (multiplicando el número debloquespara obtener la información en bytes).
Respuesta2
Esto debería funcionar. Es un poco lento y utiliza todos los usuarios en su /etc/passwd, pero eso es fácil de cambiar y no estoy seguro de qué tipo de usuarios tiene ( lastlog
supongo que también funcionaría).
Tenga en cuenta que esto utiliza el directorio de trabajo actual (consulte el find .
)
El oneliner:
for user in $(cut -d: -f1 < /etc/passwd); do echo -en "$user has:\t"; find . -user $user -type f -print0 | du --files0-from=- --total -sh | tail -n1 ; done
Aquí es lo mismo, pero un poco más detallado:
# Read all lines in /etc/password, use ":" as field separator and print first field
for user in $(cut -d: -f1 < /etc/passwd); do
# Print username, -e to allow \t, -n to skip newline
echo -en "$user is using:\t"
# Find all files owned by $user, print found files to stdout and terminate
# with a null character (thus circumventing the long file list problem).
# let `du` read from null terminated stdin usint --files0-from=-, make a total,
# make a summary and make it human readable, then only print the last line
# containing the total
find . -user "$user" -type f -print0 | du --files0-from=- --total -sh | tail -n1
done
Respuesta3
Calcular el espacio en disco ocupado por los archivos propiedad de cada usuario
Este bash
shellscript utiliza
find
para encontrar a los dueños- un
for
bucle con unafind
línea de comando para encontrar todos los archivos que pertenecen a cada propietario- y canalizar los nombres de los archivos a
du
- y canalizar los nombres de los archivos a
- después de que
du
el resultado se procese posteriormente para que sea fácil de leer.
El shellscript es bastante rápido cuando se prueba en particiones con muchos archivos.
#!/bin/bash
# store owners in variable
user=$(whoami)
if [ "$user" != "root" ]
then
echo "Run with elevated permissions (as root or with sudo)"
exit
elif ! test -d "$1"
then
echo "Enter a target directory as parameter"
exit
fi
owners=$(find "$1" -printf "%u\n"|sort | uniq)
#echo "$owners"
leng=0
for i in $owners
do
if [ ${#i} -gt $leng ]
then
leng=${#i}
fi
done
#echo "$leng"
skip=$((leng - 4))
spc=$(for ((i=0;i<skip;i++)); do printf " "; done)
printf "User $spc Size\n---- $spc ----\n"
for i in $owners
do
skip=$((leng - ${#i}))
spc=$(for ((i=0;i<skip;i++)); do printf " "; done)
printf "$i $spc "
find "$1" -type f -user "$i" -print0 | du --files0-from=- --total -sh |
tail -n1 | cut -f 1
done
Ejemplos de demostración
Asumiendo el nombredisk-usage-by-owner
ubuntu@ubuntu:~$ ./disk-usage-by-owner
Run with elevated permissions (as root or with sudo)
ubuntu@ubuntu:~$ sudo ./disk-usage-by-owner
Enter a target directory as parameter
Diálogo en un impulso vivo y persistente.
ubuntu@ubuntu:~/bin$ sudo ./disk-usage-by-owner /cdrom
User Size
---- ----
root 1.9G
ubuntu@ubuntu:~/bin$ sudo ./disk-usage-by-owner /home
User Size
---- ----
root 0
ubuntu 1.9G
ubuntu@ubuntu:~/bin$ sudo ./disk-usage-by-owner /media/ubuntu/casper-rw
User Size
---- ----
_apt 0
colord 44K
gdm 288K
man 628K
root 1007M
syslog 127M
systemd-timesync 0
ubuntu 1.9G
Los enlaces duros se cuentan solo una vez
$ sudo find . -user root -ls
56492055 1024 -rw-r--r-- 3 root root 1048576 jan 16 23:41 ./owned\ by\ root\ hard-linked
56492055 1024 -rw-r--r-- 3 root root 1048576 jan 16 23:41 ./owned\ by\ root
56492055 1024 -rw-r--r-- 3 root root 1048576 jan 16 23:41 ./sub/owned\ by\ root
$ sudo ./disk-usage-by-owner .
User Size
---- ----
root 1,0M
sudodus 32K
$ du .
4 ./sub
1064 .
Respuesta4
Esto podría ser un poco más rápido si tienes las versiones correctas de find, stat y awk:
find . -type f -exec stat -c "%U %s" {} \; | awk '{sum[$1]+=$2} END {for (u in sum) {printf("%s: %d\n", u, sum[u])}}'
Esto ejecutará el comando stat(1) en todos los archivos encontrados por el comando find(1). La estadística imprimirá el nombre de usuario y el tamaño del archivo. Luego esto pasará a awk. El comando awk simplemente resume todos los tamaños de todos los archivos de un usuario determinado. Una vez que se hayan procesado todos los archivos, imprimirá todos los usuarios que están en la lista de suma, junto con el tamaño total de todos los archivos de ese usuario.