ASPICON GmbH Hartmannstraße 7
D-09111 Chemnitz
Fon +49.371.909515-100
Fax +49.371.909515-199
Email info@aspicon.de


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