Linux 서버에서 각 사용자가 차지하는 크기를 확인해야 합니다(모든 파일은 내 데이터 폴더에 반복적으로 있음).
아래 코드를 사용하면 모든 파일과 해당 사용자를 얻을 수 있지만 나중에 그룹화하고 합산하는 방법을 모르겠습니다.
#> find . -type f -ls | sort -k5
이 문제를 해결할 아이디어가 있는 사람이 있나요?
답변1
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}'
사용자당 디스크 사용량을 바이트 단위로 보고합니다. 마찬가지로 du
하드 링크를 여러 번 계산하지 않도록 주의하세요.
find
각 파일의 장치+inode 번호( %D+%i
)(동일 파일에 대한 하드 링크의 경우 동일함), 사용자 이름 및 디스크 사용량(512바이트 단위)을 인쇄합니다.
:
일반적으로 사용자 이름에는 사용자 데이터베이스에 있는 것처럼 이러한 필드 구분 기호가 포함되어 있지 않기 때문에 필드 구분 기호로 사용됩니다(예: /etc/passwd
또는 의 출력 getent passwd
).
awk
이 목록은 첫 번째 필드가 아직 존재하지 않는 각 파일에 대해 du
사용자 이름(두 번째 필드)으로 색인화된 연관 배열을 업데이트하는 곳 으로 공급됩니다 .$2
seen
에서는 END
연관 배열의 요소를 반복하여 각 사용자의 누적 디스크 사용량(사용자 수를 곱함)을 보고합니다.조각정보를 바이트 단위로 가져옵니다.)
답변2
이것은 작동합니다. 약간 느리고 /etc/passwd의 모든 사용자를 사용하지만 변경하기 쉽습니다. 어떤 종류의 사용자가 있는지 잘 모르겠습니다( lastlog
그것도 괜찮은 것 같아요)
이는 현재 작업 디렉토리를 사용한다는 점에 유의하세요( 참조 find .
).
하나의 선:
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
이는 동일하지만 조금 더 자세히 설명합니다.
# 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
답변3
각 사용자가 소유한 파일이 차지하는 드라이브 공간을 계산합니다.
이 bash
쉘 스크립트는
find
소유자 찾기for
find
명령줄을 사용하여 각 소유자에게 속한 모든 파일을 반복합니다.- 파일 이름을 다음으로 파이프하십시오.
du
- 파일 이름을 다음으로 파이프하십시오.
du
결과를 더 쉽게 읽을 수 있도록 후 처리합니다.
많은 수의 파일이 있는 파티션에서 테스트할 때 쉘 스크립트는 매우 빠릅니다.
#!/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
데모 예시
가상의 이름disk-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
운전 중 끊임없는 실시간 대화
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
하드 링크는 한 번만 계산됩니다.
$ 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 .
답변4
올바른 버전의 find, stat 및 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])}}'
그러면 find(1) 명령으로 찾은 모든 파일에 대해 stat(1) 명령이 실행됩니다. stat는 사용자 이름과 파일 크기를 인쇄합니다. 그런 다음 awk로 전달됩니다. awk 명령은 단순히 특정 사용자에 대한 모든 파일의 모든 크기를 요약합니다. 모든 파일이 처리되면 모든 사용자의 전체 목록과 해당 사용자에 대한 모든 파일의 전체 크기가 인쇄됩니다.