Linux awk-Befehl: Textverarbeitung

LinuxLinuxBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

Willkommen in der Welt der Textverarbeitung mit AWK. In diesem Lab lernen Sie, wie Sie den awk-Befehl verwenden, um Protokolldateien (Log-Dateien) zu analysieren, eine häufige Aufgabe für Systemadministratoren und Datenanalysten. AWK ist ein leistungsstarkes Tool zur Verarbeitung strukturierter Textdaten in Linux, das es Ihnen ermöglicht, Informationen effizient zu extrahieren, zu filtern und zu transformieren.

Stellen Sie sich vor, Sie sind ein junger Systemadministrator, der mit der Analyse von Serverprotokollen beauftragt ist, um potenzielle Sicherheitsbedrohungen und Leistungsprobleme zu identifizieren. Der awk-Befehl wird Ihr Hauptwerkzeug für diese Aufgabe sein und Ihnen ermöglichen, schnell durch große Protokolldateien zu wühlen und sinnvolle Erkenntnisse zu gewinnen.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL linux(("Linux")) -.-> linux/BasicFileOperationsGroup(["Basic File Operations"]) linux(("Linux")) -.-> linux/TextProcessingGroup(["Text Processing"]) linux/BasicFileOperationsGroup -.-> linux/touch("File Creating/Updating") linux/BasicFileOperationsGroup -.-> linux/cat("File Concatenating") linux/BasicFileOperationsGroup -.-> linux/head("File Beginning Display") linux/TextProcessingGroup -.-> linux/grep("Pattern Searching") linux/TextProcessingGroup -.-> linux/awk("Text Processing") linux/TextProcessingGroup -.-> linux/sort("Text Sorting") linux/TextProcessingGroup -.-> linux/uniq("Duplicate Filtering") subgraph Lab Skills linux/touch -.-> lab-388493{{"Linux awk-Befehl: Textverarbeitung"}} linux/cat -.-> lab-388493{{"Linux awk-Befehl: Textverarbeitung"}} linux/head -.-> lab-388493{{"Linux awk-Befehl: Textverarbeitung"}} linux/grep -.-> lab-388493{{"Linux awk-Befehl: Textverarbeitung"}} linux/awk -.-> lab-388493{{"Linux awk-Befehl: Textverarbeitung"}} linux/sort -.-> lab-388493{{"Linux awk-Befehl: Textverarbeitung"}} linux/uniq -.-> lab-388493{{"Linux awk-Befehl: Textverarbeitung"}} end

Untersuchung der Protokolldatei

Beginnen wir mit der Untersuchung des Inhalts unserer Beispielprotokolldatei (Log-Datei). Diese Datei enthält simulierte Server-Zugriffsprotokolle, die wir im Laufe dieses Labs analysieren werden.

Zunächst navigieren Sie in das Projektverzeichnis:

cd ~/project

Nun lassen Sie uns die ersten paar Zeilen der Protokolldatei anzeigen:

head -n 5 server_logs.txt

Sie sollten eine Ausgabe ähnlich der folgenden sehen:

2023-08-01 08:15:23 192.168.1.100 GET /index.html 200
2023-08-01 08:16:45 192.168.1.101 GET /about.html 200
2023-08-01 08:17:30 192.168.1.102 POST /login.php 302
2023-08-01 08:18:12 192.168.1.103 GET /products.html 404
2023-08-01 08:19:05 192.168.1.104 GET /services.html 200

Diese Protokolldatei enthält Informationen über Serveranfragen, einschließlich Datum und Uhrzeit, IP-Adresse, HTTP-Methode, angefordertes Ressourcen und Statuscode.

Grundlegende AWK-Nutzung - Ausgabe bestimmter Felder

Nachdem wir nun die Struktur unserer Protokolldatei (Log-Datei) gesehen haben, verwenden wir AWK, um spezifische Informationen zu extrahieren. Standardmäßig teilt AWK jede Zeile in Felder auf, wobei Leerzeichen als Trennzeichen dienen. Wir können auf diese Felder mit $1, $2 usw. verweisen, wobei $1 das erste Feld, $2 das zweite Feld und so weiter ist.

Lassen Sie uns die IP-Adressen (das dritte Feld) aus unserer Protokolldatei extrahieren:

awk '{print $3}' server_logs.txt | head -n 5

Sie sollten eine Ausgabe ähnlich der folgenden sehen:

192.168.1.100
192.168.1.101
192.168.1.102
192.168.1.103
192.168.1.104

In diesem Befehl:

  • awk '{print $3}' weist AWK an, das dritte Feld jeder Zeile auszugeben.
  • Wir leiten (|) die Ausgabe an head -n 5 weiter, um die Anzeige auf die ersten 5 Zeilen zu beschränken.

Nun lassen Sie uns sowohl die IP-Adresse als auch die angeforderte Ressource ausgeben:

awk '{print $3, $5}' server_logs.txt | head -n 5

Ausgabe:

192.168.1.100 /index.html
192.168.1.101 /about.html
192.168.1.102 /login.php
192.168.1.103 /products.html
192.168.1.104 /services.html

Hier geben wir das dritte Feld (IP-Adresse) und das fünfte Feld (angeforderte Ressource) für jede Zeile aus.

Filtern von Protokolleinträgen

Eine Stärke von AWK liegt in seiner Fähigkeit, Daten basierend auf Bedingungen zu filtern. Nutzen wir diese Funktion, um alle POST-Anfragen in unserer Protokolldatei zu finden, da diese möglicherweise sichererheitsrelevanter sind als GET-Anfragen.

Führen Sie den folgenden Befehl aus:

awk '$4 == "POST" {print $0}' server_logs.txt

Lassen Sie uns die Syntax dieses Befehls analysieren, um zu verstehen, wie das Filtern mit AWK funktioniert:

  1. $4 == "POST" – Dies ist ein Muster oder eine Bedingung, die AWK für jede Zeile auswertet:

    • $4 bezieht sich auf das vierte Feld in der aktuellen Zeile (in unserer Protokolldatei handelt es sich hierbei um die HTTP-Methode).
    • == ist der Gleichheitsoperator, der prüft, ob zwei Werte gleich sind.
    • "POST" ist die Zeichenkette, mit der wir vergleichen.
  2. {print $0} – Dies ist die Aktion, die AWK ausführt, wenn die Bedingung wahr ist:

    • Die geschweiften Klammern {} umschließen die Aktion.
    • print ist der Befehl zum Ausgeben von Text.
    • $0 repräsentiert die gesamte aktuelle Zeile (alle Felder).

Die Befehlsstruktur folgt dem AWK-Muster: Bedingung {Aktion}. AWK liest jede Zeile, und wenn die Bedingung als wahr ausgewertet wird, führt es die Aktion aus. Wenn keine Bedingung angegeben wird (wie in unseren früheren Beispielen), wird die Aktion für jede Zeile ausgeführt.

Sie sollten eine Ausgabe ähnlich der folgenden sehen:

2023-08-01 08:17:30 192.168.1.102 POST /login.php 302
2023-08-01 09:23:45 192.168.1.110 POST /submit_form.php 200
2023-08-01 10:45:12 192.168.1.115 POST /upload.php 500

Jetzt finden wir alle Anfragen, die mit einem 404-Status (Nicht gefunden) endeten:

awk '$6 == "404" {print $1, $2, $5}' server_logs.txt

Dieser Befehl folgt dem gleichen Muster, hat aber andere Werte:

  • Die Bedingung $6 == "404" prüft, ob das sechste Feld (Statuscode) gleich 404 ist.
  • Die Aktion {print $1, $2, $5} gibt nur bestimmte Felder aus:
    • $1 – Erstes Feld (Datum)
    • $2 – Zweites Feld (Uhrzeit)
    • $5 – Fünftes Feld (angeforderte Ressource)

Diese selektive Ausgabe ermöglicht es Ihnen, sich nur auf die benötigten Informationen zu konzentrieren.

Ausgabe:

2023-08-01 08:18:12 /products.html
2023-08-01 09:30:18 /nonexistent.html
2023-08-01 11:05:30 /missing_page.html

Sie können mehrere Bedingungen mit logischen Operatoren kombinieren:

  • && für UND (beide Bedingungen müssen wahr sein)
  • || für ODER (mindestens eine Bedingung muss wahr sein)
  • ! für NICHT (negiert eine Bedingung)

Beispielsweise können Sie alle POST-Anfragen finden, die zu einem Fehler geführt haben (Statuscode >= 400):

awk '$4 == "POST" && $6 >= 400 {print $0}' server_logs.txt

Diese Filter können Ihnen helfen, potenzielle Probleme oder verdächtige Aktivitäten in Ihren Serverprotokollen schnell zu identifizieren.

Zählen und Zusammenfassen von Daten

AWK eignet sich hervorragend zum Zählen von Vorkommen und zum Zusammenfassen von Daten. Lassen Sie uns es nutzen, um die Anzahl der Anfragen für jeden HTTP-Statuscode zu zählen.

Führen Sie diesen Befehl aus:

awk '{count[$6]++} END {for (code in count) print code, count[code]}' server_logs.txt | sort -n

Dieser Befehl ist komplexer, also lassen Sie uns ihn Schritt für Schritt zerlegen:

  1. {count[$6]++} - Dies ist die Hauptaktion, die für jede Zeile ausgeführt wird:

    • count ist ein Array (assoziatives Array oder Wörterbuch), das wir erstellen
    • [$6] verwendet den Wert des 6. Feldes (Statuscode) als Array-Index/Schlüssel
    • ++ ist der Inkrementoperator, der den aktuellen Wert um 1 erhöht
    • Somit erhöhen wir für jede Zeile den Zähler für den spezifischen gefundenen Statuscode
  2. END {for (code in count) print code, count[code]} - Dies wird nach der Verarbeitung aller Zeilen ausgeführt:

    • END ist ein spezielles Muster, das das Ende der Eingabe übereinstimmt
    • {...} enthält die Aktion, die nach der Verarbeitung aller Eingaben ausgeführt wird
    • for (code in count) ist eine Schleife, die alle Schlüssel im count-Array durchläuft
    • print code, count[code] gibt jeden Statuscode und seine Anzahl aus
  3. | sort -n - Leitet die Ausgabe an den Sortierbefehl weiter, der numerisch sortiert

Wenn AWK ein Array wie count[$6]++ verarbeitet, passiert automatisch Folgendes:

  • Es wird das Array erstellt, wenn es nicht existiert
  • Es wird ein neues Element mit dem Wert 0 erstellt, wenn der Schlüssel nicht existiert
  • Dann wird der Wert um 1 erhöht

Sie sollten eine Ausgabe ähnlich dieser sehen:

200 3562
301 45
302 78
304 112
400 23
403 8
404 89
500 15

Diese Zusammenfassung zeigt Ihnen schnell die Verteilung der Statuscodes in Ihrer Protokolldatei.

Jetzt finden wir die 5 am häufigsten angeforderten Ressourcen:

awk '{count[$5]++} END {for (resource in count) print count[resource], resource}' server_logs.txt | sort -rn | head -n 5

Dieser Befehl folgt einem ähnlichen Muster mit einigen Änderungen:

  1. {count[$5]++} - Zählt die Vorkommen des 5. Feldes (die angeforderte Ressource)
  2. END {for (resource in count) print count[resource], resource} - Nach der Verarbeitung aller Zeilen:
    • Gibt zuerst die Anzahl aus, gefolgt von der Ressource
    • Diese Reihenfolgeänderung erleichtert die numerische Sortierung nach der Anzahl
  3. | sort -rn - Sortiert numerisch in umgekehrter Reihenfolge (höchste Anzahlen zuerst)
  4. | head -n 5 - Begrenzt die Ausgabe auf die ersten 5 Zeilen (die 5 besten Ergebnisse)

Ausgabe:

1823 /index.html
956 /about.html
743 /products.html
512 /services.html
298 /contact.html

Diese AWK-Befehle demonstrieren die Stärke der Verwendung von Arrays zum Zählen und Zusammenfassen. Sie können dieses Muster anpassen, um jedes Feld oder jede Kombination von Feldern in Ihren Daten zu zählen.

Beispielsweise können Sie die Anzahl der Anfragen pro IP-Adresse zählen:

awk '{count[$3]++} END {for (ip in count) print ip, count[ip]}' server_logs.txt

Um Anfragen sowohl nach Methode als auch nach Status zu zählen:

awk '{key=$4"-"$6; count[key]++} END {for (k in count) print k, count[k]}' server_logs.txt

Diese Zusammenfassungen können Ihnen helfen, Verkehrsmuster zu verstehen und beliebte (oder problematische) Ressourcen auf Ihrem Server zu identifizieren.

Erstellen eines einfachen Berichts

Für unsere letzte Aufgabe erstellen wir einen einfachen HTML-Bericht, der einige Schlüsselinformationen aus unserer Protokolldatei zusammenfasst. Wir verwenden für diese komplexere Operation ein separates AWK-Skript.

Zuerst erstellen Sie eine Datei mit dem Namen log_report.awk mit folgendem Inhalt:

Tipp: Kopieren Sie den folgenden Inhalt und fügen Sie ihn in Ihr Terminal ein, um die Datei zu erstellen.

cat << 'EOF' > log_report.awk
BEGIN {
    print "<html><body>"
    print "<h1>Server Log Summary</h1>"
    total = 0
    errors = 0
}

{
    total++
    if ($6 >= 400) errors++
    ip_count[$3]++
    resource_count[$5]++
}

END {
    print "<p>Total requests: " total "</p>"
    print "<p>Error rate: " (errors/total) * 100 "%</p>"
    
    print "<h2>Top 5 IP Addresses</h2>"
    print "<ul>"
    for (ip in ip_count) {
        top_ips[ip] = ip_count[ip]
    }
    n = asort(top_ips, sorted_ips, "@val_num_desc")
    for (i = 1; i <= 5 && i <= n; i++) {
        for (ip in ip_count) {
            if (ip_count[ip] == sorted_ips[i]) {
                print "<li>" ip ": " ip_count[ip] " requests</li>"
                break
            }
        }
    }
    print "</ul>"
    
    print "<h2>Top 5 Requested Resources</h2>"
    print "<ul>"
    for (resource in resource_count) {
        top_resources[resource] = resource_count[resource]
    }
    n = asort(top_resources, sorted_resources, "@val_num_desc")
    for (i = 1; i <= 5 && i <= n; i++) {
        for (resource in resource_count) {
            if (resource_count[resource] == sorted_resources[i]) {
                print "<li>" resource ": " resource_count[resource] " requests</li>"
                break
            }
        }
    }
    print "</ul>"
    
    print "</body></html>"
}
EOF

Lassen Sie uns dieses AWK-Skript Abschnitt für Abschnitt verstehen:

  1. BEGIN-Block: Wird vor der Verarbeitung von Eingabezeilen ausgeführt

    BEGIN {
        print "<html><body>"  ## Start HTML structure
        print "<h1>Server Log Summary</h1>"
        total = 0  ## Initialize counter for total requests
        errors = 0  ## Initialize counter for error requests
    }
  2. Hauptverarbeitungsblock: Wird für jede Zeile der Eingabedatei ausgeführt

    {
        total++  ## Increment total request counter
        if ($6 >= 400) errors++  ## Count error responses (status codes >= 400)
        ip_count[$3]++  ## Count requests by IP address (field 3)
        resource_count[$5]++  ## Count requests by resource (field 5)
    }
  3. END-Block: Wird nach der Verarbeitung aller Eingabezeilen ausgeführt

    END {
        ## Print summary statistics
        print "<p>Total requests: " total "</p>"
        print "<p>Error rate: " (errors/total) * 100 "%</p>"
    
        ## Process and print top 5 IP addresses
        #...
    
        ## Process and print top 5 requested resources
        #...
    
        print "</body></html>"  ## End HTML structure
    }

Lassen Sie uns die Sortierlogik für die Top-IPs untersuchen (der Abschnitt für die Ressourcen funktioniert auf die gleiche Weise):

## Copy the counts to a new array for sorting
for (ip in ip_count) {
    top_ips[ip] = ip_count[ip]
}

## Sort the array by value in descending order
n = asort(top_ips, sorted_ips, "@val_num_desc")

## Print the top 5 entries
for (i = 1; i <= 5 && i <= n; i++) {
    ## Find the original IP that matches this count
    for (ip in ip_count) {
        if (ip_count[ip] == sorted_ips[i]) {
            print "<li>" ip ": " ip_count[ip] " requests</li>"
            break
        }
    }
}

In diesem Skript:

  • Die asort()-Funktion sortiert das Array.
  • "@val_num_desc" ist ein spezielles Argument, das die Funktion anweist, das Array numerisch nach Werten in absteigender Reihenfolge zu sortieren.
  • Die verschachtelten Schleifen finden und geben die Top-5-Einträge aus.

Jetzt führen wir unser AWK-Skript aus, um den Bericht zu generieren:

awk -f log_report.awk server_logs.txt > log_report.html

Die Option -f teilt AWK mit, das Skript aus der angegebenen Datei zu lesen:

  • -f log_report.awk - Liest das AWK-Skript aus der Datei log_report.awk.
  • server_logs.txt - Verarbeitet diese Datei mit dem Skript.
  • > log_report.html - Leitet die Ausgabe in die Datei log_report.html um.

Sie können den Inhalt des Berichts mit dem Befehl cat anzeigen:

cat log_report.html

Dieser Bericht bietet eine Zusammenfassung der Gesamtanzahl der Anfragen, der Fehlerrate, der Top-5-IP-Adressen und der Top-5 angeforderten Ressourcen. In einer realen Anwendung könnten Sie diese HTML-Datei in einem Webbrowser öffnen, um eine formatierte Ansicht zu erhalten.

Der Ansatz, den wir in diesem Skript verwendet haben, zeigt, wie AWK für komplexere Datenanalyseaufgaben eingesetzt werden kann. Sie können dieses Skript erweitern, um zusätzliche Statistiken oder andere Visualisierungen gemäß Ihren spezifischen Anforderungen hinzuzufügen.

Zusammenfassung

Herzlichen Glückwunsch! Sie haben dieses Lab zur Verwendung des AWK-Befehls für die Protokollanalyse (Log-Analyse) abgeschlossen. Lassen Sie uns zusammenfassen, was Sie gelernt haben:

  1. Grundlegende AWK-Nutzung: Ausgabe bestimmter Felder aus einer strukturierten Textdatei.
  2. Filtern von Daten: Verwenden von Bedingungen in AWK, um bestimmte Protokolleinträge auszuwählen.
  3. Zählen und Zusammenfassen: Verwenden von AWK, um Statistiken aus Protokolldaten zu generieren.
  4. Erstellen von Berichten: Schreiben von komplexeren AWK-Skripten, um formatierte Berichte zu generieren.

Diese Fähigkeiten werden Ihnen bei der Analyse von Protokolldateien, der Verarbeitung von Daten und der Erstellung von Berichten in Ihrer zukünftigen Arbeit als Systemadministrator oder Datenanalyst unschätzbar sein.

Hier sind einige zusätzliche AWK-Parameter und -Funktionen, die wir in diesem Lab nicht behandelt haben:

  • -F: Gibt ein anderes Feldtrennzeichen als Leerzeichen an.
  • -v: Weist einer Variablen einen Wert zu.
  • NR: Eine integrierte Variable, die die aktuelle Datensatznummer darstellt.
  • NF: Eine integrierte Variable, die die Anzahl der Felder im aktuellen Datensatz darstellt.
  • BEGIN- und END-Blöcke: Spezielle Muster für die Initialisierung und Finalisierung.
  • Integrierte Funktionen: Mathematische Funktionen, Zeichenkettenfunktionen und mehr.

Denken Sie daran, dass Übung der Schlüssel zum Beherrschen von AWK ist. Versuchen Sie, die Befehle und Skripte aus diesem Lab zu ändern, um verschiedene Aspekte der Protokolldatei zu analysieren oder andere Arten von strukturierten Textdaten zu verarbeiten.

Ressourcen