staging.inyokaproject.org

Logfile als CSV Tabelle mit mehreren Spalten

Status: Gelöst | Ubuntu-Version: Ubuntu GNOME 20.04 (Focal Fossa)
Antworten |

minix

Anmeldungsdatum:
9. August 2021

Beiträge: 2

Hallo,

ich bin neu hier und benötige eure Unterstützung bei folgendem Problem: In einem bestimmten Zeitanstand wird die directory usage Ausgabe von "du -Psx * 2>/dev/null" fortlaufend in ein Logfile geschrieben. Aus diesem Logfile soll nun eine Semikolon separierte CSV Tabelle werden, welche pro Spalte als Tabellenkopf das Datum jedes "du" Lauf's zeigt. Es kann auch vorkommen, dass zwischenzeitlich ein Verzeichnis hinzukommt oder gelöscht wird. Hier ein Beispiel:

du-Logfile.log
#	01.06.2021
11	dir1
111	dir2
11	dir3
1111	dir4
1111	dir5
#	02.06.2021
22	dir1
222	dir2
22	dir3
2222	dir4
2222	dir5
22	dir6
#	03.06.2021
33	dir1
333	dir2
33	dir3
3333	dir5
33	dir6
Tabelle.csv
#	;01.06.2021;	02.06.2021;	03.06.2021;
dir1;	11;		22;		33;
dir2;	111;		222;		333;
dir3;	11;		22;		33;
dir4;	1111;		2222;		;
dir5;	1111;		2222;		3333;
dir6;	;		22;		33;

Ich suche eine Lösung als bash und/oder awk Skript. Meine Versuche über ein Arry sind beim nächsten Durchlauf, also beim nächsten Datum gescheitert. Ziel ist es, über die Zeit eine Speicherplatz-/Nutzungkurve zuerstellen.

Vielen Dank schon mal für eure Unterstützung!

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

Habe jetzt keine Zeit, aber vielleicht hilft das als Anfang:

1
2
$ awk '/^#/ {dates[count++]=$2} !/^#/ {} END {print count, dates[count-1]}' du-Logfile.log 
3 03.06.2021

Du musst in der leeren geschweiften Klammer dann die Verzeichnisse und Volumina verarbeiten. Am Ende dann in END alles ausgeben. Ist ein bisschen eklig mit mehrdimensionalen Arrays. In Ruby wäre das eleganter.

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

Mit awk könnte man sowas in der Art versuchen (die Datei dem Skript als Argument übergeben):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/awk -f
BEGIN {
        c=-1
}
/^#/ {
        c++
        dates[c]=$2
        next
}
/^[0-9]+/ {
        d = dates[c]
        folder=$2
        used_dirs[folder]++
        dirs[folder, d]=$1
        next
}
END {
        printf "#"
        for (d in dates){
                printf ";%s", dates[d]
        }
        printf "\n";
        asorti(used_dirs, sorted_dirs)
        for (d in sorted_dirs){
                printf "%s;", sorted_dirs[d]
                for (s in dates){
                        printf "%s;", dirs[sorted_dirs[d], dates[s]]
                }
                printf "\n"
        }
}

Ich würde das ja lieber mit Python3 machen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/env python3
import csv
import datetime
import fileinput
import sys

dirs = set()
dates = set()
data = {}

for line in fileinput.input():
    if line.startswith('#'):
        _, date = line.split()
        date = datetime.datetime.strptime(date, "%d.%m.%Y")
        dates.add(date)
    elif line[0].isdigit():
        bs, d = line.split()
        dirs.add(d)
        data[(d, date)] = bs

writer = csv.writer(sys.stdout, ["directory", *dates], delimiter=';')
writer.writerow(["directory", *(d.strftime("%d.%m.%Y") for d in dates)])
for d in sorted(dirs):
    writer.writerow([d] + [data.get((d, date), "") for date in sorted(dates)])

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13242

OK, hier ist ein Ansatz für die geschweiften Klammern:

  1. den Dateinamen in einem assoziativen Array "files" merken

  2. das Volumen in einem anderen assoziativen Array "volumes" merken mit Schlüssel ($2, date) (also Dateiname und Datum) merken

... und END:

  1. Iterieren über alle Schlüssel von "files"

  2. pro Durchlauf, iterieren über alle Werte von "dates"

  3. Ausgabe ";" falls nicht erster Eintrag

  4. Ausgabe volumes[file, date]

Ggf. musst Du noch die Schlüssel von "files" mit asorti() sortieren, damit alles schön angeordnet wird. Auf die Leerzeichen in Deiner Beispielausgabe würde ich verzichten, weil die für CSV nicht benötigt werden.

minix

(Themenstarter)

Anmeldungsdatum:
9. August 2021

Beiträge: 2

Was soll ich sagen? Vielen, vielen Dank! Ich sitze an einer Lösung ca. 3 Wochen und hab immer mal wieder Versuche unternommen. Awk und Arrays, da bin ich jetzt ein großes Stück weiter gekommen! Danke!

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11278

Falls das ein großer zeitlicher Verlauf mit vielen Datenpunkten wird, würde ich mir stark überlegen die Werte in eine Datenbank wie InfluxDB zu schreiben und das ganze dann z.B. mit Grafana zu visualisieren, dann kann man sich viel Skripterei ersparen.

Antworten |