Platte voll! Wer hat Schuld?
Meldung vom 05.06.2011
Sobald eine größere Platte eingebaut oder ein Volume vergrößert wurde, ist es meist auch schon wieder voll. Im allgemeinen gestaltet es sich dann schwierig, unter der Vielzahl der Unterverzeichnisse das jenige zu finden, das den meisten Platz belegt - sei es durch Generationen von Logfiles, vergessene Downloads des vorletzten Linuxreleases oder das komplette Installimage der Oracle Database 11.2 usw.
Man kann sich jetzt mehr oder weniger mühsam durch die einzelnen Verzeichnisse "hangeln" auf der Suche nach dem Top-Verbraucher, indem man die Befehle "du" und "sort" zu Rate zieht. Beispielsweise würde man typischerweise so nach einem übermäßig gefüllten Verzeichnis unterhalb /var suchen:
# du -sxk /var/*|sort -n
0 /var/mail
4 /var/account
4 /var/crash
4 /var/cvs
4 /var/games
4 /var/gdm
4 /var/local
4 /var/nis
4 /var/opt
4 /var/preserve
4 /var/yp
8 /var/db
8 /var/empty
12 /var/www
16 /var/lock
16 /var/lost+found
128 /var/spool
320 /var/run
11936 /var/cfengine
16260 /var/log
46008 /var/cache
96940 /var/lib
5796128 /var/tmp
/var/tmp trägt hier am meisten zur Volumeauslastung bei und ist offensichtlich (dem Namen nach) auch ein Kandidat zum Löschen. Deshalb würde man nun in dessen Unterverzeichnissen weitersuchen:
# du -sxk /var/tmp/*|sort -n
252 /var/tmp/NameSearch_APEX_Demoapp_UTF8_4_0_0_Db11202.sql
17604 /var/tmp/kdecache-tso
25752 /var/tmp/p6880880_101000_Linux-x86-64.zip
141188 /var/tmp/B30974-01.zip
591500 /var/tmp/B30973-01.zip
684108 /var/tmp/as_linux_x86_oim_oif_101401_disk1.cpio
696388 /var/tmp/as_linux_x86_oim_oif_101401_disk2.cpio
3635280 /var/tmp/c-rep-01
# du -sxk /var/tmp/c-rep-01/*|sort -n
...und so weiter.
Wir haben statt dessen ein kleines bash-Skript mit Namen "dutree.sh" geschrieben, das ausgehend von einem Startverzeichnis rekursiv die Verzeichnisstruktur der Platte durchsucht, "du" auf jedes der Verzeichnisse anwendet und das Ergebnis in einer Baumstruktur darstellt. Die Ausgabe wird je Verzeichnis aufsteigend nach Größe sortiert, so dass man je Baumlevel von unten beginnend nach oben die lukrativsten Löschkandidaten ausfindig machen kann. Um eine gewisse Vorauswahl treffen zu können, kann dem Skript ein Füllstand mitgegeben werden, den ein Verzeichnis mindestens aufweisen muss, um in die Ausgabe einbezogen zu werden. Im folgenden Beispiel wird das /var-Verzeichnis nach allen Verzeichnissen durchsucht, die (zzgl. ihrer Unterverzeichnisse) mindestens 100M belegen:
# ./dutree.sh /var 100m
5815M /var/tmp/
. 176M . /var/tmp/kdecache-tso/
.. 172M .. /var/tmp/kdecache-tso/kpc/
. 3550M . /var/tmp/c-rep-01/
.. 3550M .. /var/tmp/c-rep-01/MREP/
... 3502M ... /var/tmp/c-rep-01/MREP/backupset/
.... 641M .... /var/tmp/c-rep-01/MREP/backupset/2011_02_24/
.... 2860M .... /var/tmp/c-rep-01/MREP/backupset/2011_03_01/
------------------------- snip --------------------
#! /bin/bash
#
# This script utilizes the "du" command to recursively build a disk usage tree.
# Output is ascendingly ordered by used size per directory level. So you can see the most space
# consuming directories at bottom. Additionally to the directory's usage sum, each subdirectory's
# sum is being displayed.
#
# Usage: dutree [BASEDIR [SIZE_THREASHOLD[b,k,m,g]]]
# dutree -h
# BASEDIR start directory tree from this base directory (default: .)
# SIZE_THREASHOLD only display directories that at least sum up to a size of SIZE_THREASHOLD (default: 0)
# b,k,m,g SIZE_THREASHOLD can be appended by k,m,g for convenience (default: b)
#
# (c) Copyright 2011 ASPICON GmbH
# All rights reserved.
#
# Changelog:
# 2011-03-16 Thilo Solbrig
Version 1.0
# * initial release
# print usage, if asked to
if [ "${1}" == "-h" -o "${1}" == "--help" ]; then
echo 'Usage: dutree [BASEDIR [SIZE_THREASHOLD[k,m,g]]]'
fi
BASEDIR=${1}
THRESHOLD=${2}
INDENT_CHARS="."
DIR_USAGE_SEP="\t\t\t" # separator between usage and path columns
# default base dir is current dir
if [ -z ${BASEDIR} ]; then
BASEDIR=.
fi
# defaul threashold is 0
if [ -z ${THRESHOLD} ]; then
THRESHOLD=0
else
# remove any blanks (i.e. between amount and unit) from threashold value
THRESHOLD=$(echo ${THRESHOLD}|sed 's/ //g')
fi
# normalize threashold if given in human readable format
case ${THRESHOLD} in
*[b,B])
UNIT_FACTOR=1
;;
*[k,K])
UNIT_FACTOR=1024
UNIT=K
;;
*[m,M])
UNIT_FACTOR=1048576
UNIT=M
;;
*[g,G])
UNIT_FACTOR=1073741824
UNIT=G
;;
*)
UNIT_FACTOR=1
;;
esac
# normalize threashold to bytes
THRESHOLD=$(expr $(echo ${THRESHOLD}|sed 's/[b,B,k,K,m,M,g,G]//g') \* ${UNIT_FACTOR})
recurse_subdir() {
# cycle through all entries of the specified directory
du -sxb $1/* 2>/dev/null|sort -n|while read USAGE SUBDIR; do
# handle directories exceeding the given threshold only
if [ ${USAGE} -ge ${THRESHOLD} ]; then
# replace blanks in filenames
SUBDIR=$(echo ${SUBDIR}|sed 's/ /_/g')
# handle directories only, no files etc.
if [ -d ${SUBDIR} ]; then
# print indented directory usage
# print indent
for i in $(seq 1 ${2}); do
echo -en "${INDENT_CHARS}"
done
# denormalize usage according to the unit provided
if [ ${UNIT_FACTOR} -ne 1 ]; then
USAGE=$(expr ${USAGE} / ${UNIT_FACTOR})${UNIT}
fi
# print usage
echo -en " ${USAGE}${DIR_USAGE_SEP}"
# print indented directory name
# print indent
for i in $(seq 1 ${2}); do
echo -en "${INDENT_CHARS}"
done
# print directory
echo -e " ${SUBDIR}/"
# recurse into current directory, incrementing level by 1
recurse_subdir ${SUBDIR} $(expr ${2} + 1)
fi
fi
done
}
# start at base dir, level 0
recurse_subdir ${BASEDIR} 0
------------------------- snap --------------------
Zurück






