Ein verdächtiger Hinweis auf so eine Situation ist, wenn die Abweichung zwischen du und df groß ist. Das passiert, weil kein Hardlink mehr auf die gelöschte Datei in irgendeinem Verzeichnis mehr vorhanden ist (Linkcount ist 0, Datei ist als gelöscht markiert im Dateisystem) und daher von du nicht bemerkt wird. Im Dateisystem gibt es die Datei aber noch, daher kommt die Abweichung von df.
logrotate ist so ein Kandidat für solche Geschichten, wenn das Logfile zwar wegrotiert wird, aber hinterher der loggende Prozess nicht neu gestartet wird. Dieser Prozess wird dann fröhlich weiter einen Filedescriptor beschreiben, bis er irgendwann mal beendet wird.
Finden kann man solche Prozesse zum Beispiel mit find:
t41:~$ find -L /proc/*/fd -xdev -type f -links 0 2>/dev/null
/proc/4695/fd/5
/proc/self/fd/3/5
t41:~$
Den zweiten Prozess kann man ignorieren.
Mal sehen welcher Prozess sich hinter dem ersten Prozess versteckt:
t41:~$ cat /proc/4695/cmdline; echo
mutt
~$
Ah ja. Ein cat /proc/4695/fd/5 gibt auch den Inhalt aus, es ist eine Mail, die ich gerade gelesen habe.
Mit lsof geht das ganze noch einfacher:
t41:~ [1128]# lsof +L1
COMMAND PID USER FD TYPE DEVICE SIZE NLINK NODE NAME
dhclient3 2239 root txt REG 8,1 363232 0 81742 /sbin/dhclient3
smbd 5822 root 2w REG 8,1 863 0 434171 /var/log/samba/log.smbd.1 (deleted)
smbd 5822 root 7w REG 8,1 863 0 434171 /var/log/samba/log.smbd.1 (deleted)
tail 11182 chrisbra 3r REG 8,1 104909 0 401728 /var/log/syslog.1 (deleted)
Die erste Datei ist ein Fehlalarm. Warum dort bei diesem Filedescriptor ein Linkcount von 0 angezeigt wird, verstehe ich gerade nicht. Die richtigen sind die, wo (deleted) steht.
Hm mal sehen, was wir da noch so rausfinden können:
t41:~ [1130:1]#lsof +L1 -Fnskc |awk '
/^s/ {
j=gensub(/^s/, "",1,$1)
}
/^n/ && /(deleted)/ {
i=gensub(/^n/, "",1,$1)
a[i]=j;
}
END {
for (i in a) {
s+=a[i];
print "Files: ", i , " Size: " , a[i];
}
u="B"
if (s>=1024) {
s/=1024
u="kB"};
printf("-------------------\nTotal:\t%.2f %s\nAvg:\t%.2f %s\n", s, u, s/length(a),u);
}'
Files: /var/log/samba/log.smbd.1 Size: 863
Files: /var/log/syslog.1 Size: 104909
-------------------
Total: 103,29 kB
Avg: 51,65 kB
Die 2 Prozesse verbrauchen also ca: 103 kB mehr an Platz. Ein Restart sollte reichen, um den Platz wieder freizugegeben.
Falls das aus irgendeinem Grund nicht geht, weil man die Prozesse nicht restarten kann, aber trotzdem kein Wert auf die Daten in den gelöschten Dateien legt, müßte man die Daten ungefähr folgendermaßen freigeben können:
t41:~ [1155]# for i in 5822 11182;
do find -L /proc/$i/fd -type f -links 0 -exec sh -c 'exec > {}' \; ; done
t41:~ [1156]# lsof +L1 -Fnskc |awk '
/^s/ {
j=gensub(/^s/, "",1,$1)
}
/^n/ && /(deleted)/ {
i=gensub(/^n/, "",1,$1)
a[i]=j;
}
END {
for (i in a) {
s+=a[i];
print "Files: ", i , " Size: " , a[i];
}
u="B"
if (s>=1024) {
s/=1024
u="kB"};
printf("-------------------\nTotal:\t%.2f %s\nAvg:\t%.2f %s\n", s, u, s/length(a),u);
}'
Files: /var/log/samba/log.smbd.1 Size: 0
Files: /var/log/syslog.1 Size: 0
-------------------
Total: 0,00 B
Avg: 0,00 B
Zunächst wurden mit einer Schleife alle Filedescriptoren gefunden, die zu den beiden Prozessen gehören und einen Linkcount von 0 hatten. Diese Filedescriptoren wurden einfach noch einmal durch die Shell zum Schreiben geöffnet und praktischerweise löscht die Shell dabei gleich den vorhandenen Inhalt.
Wie man anhand des zweiten mini-Scripts sieht, sind jetzt zwar immernoch 2 Prozesse vorhanden, die auf gelöschte Dateien zugreifen möchten, aber diese Dateien nehmen keinen Platz mehr weg.
Empfehlen tu ich diesen Weg aber nicht. Ich denke, dabei könnten einige Prozesse drüber stolpern. Es ist also mehr oder weniger nur ein übler Hack.
Einen Vorteil hat das Ganze übrigens auch. Versehentlich gelöschte Dateien können so schnell und einfach wieder hergestellt werden, so lange noch ein Prozess diese Dateien geöffnet hält. Ein cat /proc/5822/fd/2 > /var/log/smbd.log und schon ist die Datei wieder im Dateisystem. Funktioniert nur leider nicht mehr, wenn man die Datei schon geleert hat, wie gerade eben durch das letzte find-Statement geschehen. ;(








