Linux-Befehle, die jeder Dev kennen sollte

1. Überblick

Jeder Dev ist schon mal per SSH auf einen Server gegangen, hat ein Terminal zum Debuggen geöffnet oder eine App deployed und hat sich dann abmüht, den richtigen Befehl zu finden. Dieser Artikel fasst zusammen, welche Linux-Befehle Sie im Alltag am häufigsten brauchen: Dateiverwaltung, Suche, Textverarbeitung, Prozessüberwachung, Netzwerkprüfung und Logs. Nach dem Lesen haben Sie einen essentiellen Befehlssatz, um schnell zu debuggen, ohne ständig erneut googeln zu müssen.

Ich verwende bash auf Ubuntu/Debian als Hauptbeispiel, aber diese Befehle funktionieren auf praktisch allen Distributionen gleich.

2. Grundlegende Datei- und Verzeichnisvorgänge

mkdir -p ~/projects/order-service/src/main/java
cd ~/projects/order-service
touch application.properties
ls -la
  • mkdir -p erstellt die gesamte Verzeichnisstruktur auf einmal, meldet keinen Fehler, wenn das Verzeichnis bereits existiert.
  • touch erstellt eine leere Datei (oder aktualisiert den Zeitstempel, falls die Datei bereits existiert).
  • ls -la listet alle Dateien auf (einschließlich versteckter Dateien wie .env, .git) mit Berechtigungen, Besitzer und Größe.
drwxr-xr-x  3 nonla nonla 4096 Oct  5 10:00 .
-rw-r--r--  1 nonla nonla    0 Oct  5 10:00 application.properties

Einige Move/Delete-Befehle erfordern Vorsicht:

cp -r src/ src-backup/     # Verzeichnis rekursiv kopieren
mv OrderService.java OrderServiceImpl.java   # umbenennen oder verschieben
rm -rf target/            # rekursiv löschen, ohne zu fragen

Hinweis: rm -rf hat keinen Papierkorb — gelöscht heißt weg. Überprüfen Sie immer den Pfad mit pwd, bevor Sie diesen Befehl ausführen, besonders wenn Sie die Zeile von woanders kopiert haben.

3. Suchen mit find und grep

3.1. find — Dateien nach Bedingungen suchen

find . -name "*.java" -newer pom.xml

Dieser Befehl findet alle .java-Dateien, die nach pom.xml geändert wurden — nützlich, um zu sehen, welche Dateien sich vor dem nächsten Commit geändert haben.

find . -type f -size +10M

Findet Dateien größer als 10MB, praktisch zum Bereinigen von großen Logs oder Build-Artefakten.

3.2. grep — Inhalte in Dateien finden

grep -rn "PaymentService" --include="*.java" src/
  • -r sucht rekursiv in Unterverzeichnissen.
  • -n gibt Zeilennummern mit aus.
  • --include beschränkt die Suche auf .java-Dateien, um zu vermeiden, dass auch target/ durchsucht wird.
src/main/java/com/nonla/OrderController.java:15:    private final PaymentService paymentService;

Kombinieren Sie grep mit find über Pipe für komplexere Filter:

find . -name "*.log" | xargs grep -l "OutOfMemoryError"

xargs leitet die Liste von Dateien von find an grep -l weiter (gibt nur die Namen von Dateien aus, die das Muster enthalten, nicht den Inhalt).

4. Textverarbeitung mit awk, sed, cut

Das sind die Befehle zum Knacken von Logs — extrem mächtig, wenn Sie Daten aus langen Ausgaben extrahieren müssen.

cat access.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -5
  • awk '{print $1}' extrahiert die erste Spalte (normalerweise IP) aus jeder Log-Zeile.
  • sort | uniq -c gruppiert und zählt, wie oft jede Spalte vorkommt.
  • sort -rn sortiert absteigend nach Zahlen, head -5 nimmt die Top 5.
    152 192.168.1.10
     98 10.0.0.5
     47 172.16.0.3

Das ist die schnellste Möglichkeit, die IP-Adresse zu finden, die die meisten Anfragen gestellt hat, ohne ein Skript zu schreiben.

sed ersetzt Text direkt in einer Datei:

sed -i 's/spring.profiles.active=dev/spring.profiles.active=prod/' application.properties

-i bearbeitet die Datei direkt (in-place). Wenn Sie sicherer sein möchten, verwenden Sie sed -i.bak '...', um automatisch eine .bak-Sicherungsdatei zu erstellen.

cut teilt Spalten nach einem Trennzeichen auf — leichter als awk, wenn Sie nur eine einfache Spalte benötigen:

cat /etc/passwd | cut -d: -f1 | head -3

5. Prozesse und Systemressourcen überwachen

ps aux | grep java

Listet alle Prozesse auf, gefiltert nach Zeilen mit java — eine schnelle Möglichkeit, um zu sehen, ob Ihre Spring Boot-App ausgeführt wird und was die PID ist.

nonla    12345  2.1  5.3 2345678 432100 ?      Sl   10:00   0:15 java -jar order-service.jar

Die zweite Spalte ist die PID. Verwenden Sie diese PID, um den Prozess zu beenden oder Details anzuzeigen:

kill -15 12345     # SIGTERM senden, App erhält Zeit für sauberes Herunterfahren
kill -9 12345       # erzwungenes Beenden, nutzen Sie nur wenn -15 nicht funktioniert

Hinweis: kill -9 erlaubt der App nicht, Shutdown Hooks auszuführen (z.B. Connection-Pool schließen, Logs leeren). Versuchen Sie immer zuerst -15.

Ressourcen in Echtzeit anzeigen:

top -o %MEM

-o %MEM sortiert Prozesse nach RAM-Verbrauch — nützlich, wenn Sie einen Memory Leak vermuten. Für eine schönere Oberfläche installieren Sie htop.

Speicherplatz prüfen:

df -h
du -sh /var/log/*

df -h zeigt den Speicherplatz jeder Partition (human-readable). du -sh zeigt, wie viel Speicherplatz jedes Unterverzeichnis in /var/log belegt — sehr nützlich, wenn der Server meldet “no space left on device”.

6. Netzwerk und Ports prüfen

ss -tulnp | grep 8080
  • ss ersetzt das alte netstat, ist schneller.
  • -t TCP, -u UDP, -l lauschend, -n numerisch (keine DNS-Auflösung), -p mit Prozess.
tcp   LISTEN  0  128  0.0.0.0:8080  0.0.0.0:*  users:(("java",pid=12345,fd=45))

Sofort erkennen, dass Port 8080 vom Java-Prozess mit PID 12345 verwendet wird — sehr nützlich, wenn Sie den Fehler Address already in use erhalten.

APIs schnell mit curl testen:

curl -s -X POST http://localhost:8080/api/orders \
  -H "Content-Type: application/json" \
  -d '{"customerId":1,"amount":99.5}'

-s ist still (verbirgt die Fortschrittsanzeige), -X POST wählt die Methode, -d ist der JSON-Body. Fügen Sie -i hinzu, wenn Sie auch die Response-Header sehen möchten.

lsof verwenden Sie, wenn Sie genau wissen möchten, welche Dateien/Sockets ein Prozess öffnet:

lsof -i :8080

7. Dateiberechtigungen

chmod +x deploy.sh
chown nonla:nonla application.properties
chmod 640 .env
  • chmod +x macht das Skript ausführbar.
  • chown user:group ändert den Besitzer — erfordert normalerweise sudo, wenn die Datei einem anderen Benutzer gehört.
  • chmod 640 bedeutet: Besitzer lesen/schreiben (6), Gruppe nur lesen (4), andere haben keine Rechte (0) — Standard für sensible Dateien wie .env.
-rw-r----- 1 nonla nonla 128 Oct  5 10:00 .env

Hinweis: Verwenden Sie niemals chmod 777 in der Production. Das ist die schnellste Möglichkeit, dass jeder Benutzer auf dem Rechner sensible Dateien lesen und ändern kann.

8. Komprimierung und Dekomprimierung

tar -czvf order-service.tar.gz order-service/
tar -xzvf order-service.tar.gz -C /opt/apps/
  • -c erstellt ein Archiv, -x entpackt, -z verwendet gzip, -v ausführlich, -f gibt den Dateinamen an.
  • -C gibt beim Entpacken das Zielverzeichnis an, anstatt in das aktuelle Verzeichnis zu entpacken.

Kombinieren Sie beim Deploy mit scp oder rsync, um Dateien auf den Server hochzuladen:

scp order-service.tar.gz user@10.0.0.5:/opt/apps/
rsync -avz --progress target/*.jar user@10.0.0.5:/opt/apps/

rsync überträgt nur geänderte Daten (Delta-Übertragung) und ist viel schneller als scp, wenn Sie große Dateien mehrmals aktualisieren.

9. Logs in Echtzeit anzeigen

tail -f /var/log/order-service/app.log

-f (follow) hält das Terminal offen und zeigt neue Zeilen sofort an, wenn die Datei aktualisiert wird — ein Befehl, den Sie beim Debuggen in der Production unbedingt kennen müssen.

Logs nach Pattern filtern während Sie tail verwenden:

tail -f app.log | grep --line-buffered "ERROR"

--line-buffered ist notwendig, weil grep standardmäßig blockweise puffert. Ohne diese Flagge kann die Ausgabe verzögert werden, wenn sie über Pipe mit tail -f verbunden ist.

Wenn die App unter systemd ausgeführt wird, verwenden Sie journalctl, anstatt die Log-Datei manuell zu suchen:

journalctl -u order-service -f --since "10 minutes ago"

-u gibt die Service-Unit an, -f ist follow, --since begrenzt den Zeitraum — vermeiden Sie, Millionen von alten Log-Zeilen lesen zu müssen.

10. Linux-Befehle von Java aus ausführen

Oft müssen Sie Shell-Befehle direkt von Java-Code aus aufrufen — z.B. Speicher prüfen, bevor Sie eine große Datei schreiben:

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.List;

public class ShellRunner {

    public static String run(List<String> command) throws Exception {
        ProcessBuilder builder = new ProcessBuilder(command);
        builder.redirectErrorStream(true);
        Process process = builder.start();

        try (BufferedReader reader =
                new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String output = reader.lines().reduce("", (a, b) -> a + b + "\n");
            process.waitFor();
            return output;
        }
    }
}
  • ProcessBuilder akzeptiert eine Liste von Argumenten (nicht eine zusammengefügte Befehlszeichenfolge), um Shell-Injection zu vermeiden.
  • redirectErrorStream(true) fasst stderr mit stdout zusammen, um einen einzigen Stream zu lesen.
  • process.waitFor() blockiert den aktuellen Thread, bis der untergeordnete Prozess beendet ist.

Test mit JUnit 5 + AssertJ:

import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;

class ShellRunnerTest {

    @Test
    void shouldReturnCurrentDirectoryListing() throws Exception {
        String output = ShellRunner.run(List.of("ls", "-la"));

        assertThat(output).contains("total");
    }
}

Dieser Test führt ls -la wirklich auf dem System aus und prüft, ob die Ausgabe die Zeile total enthält (die erste Zeile, die ls -la immer ausgibt, zeigt die Gesamtzahl der Blöcke) — bestätigt, dass ProcessBuilder einen Shell-Befehl wirklich aufrufen kann.

Hinweis: Shell-Befehle von Java-Production-Code aus aufzurufen ist ein zweischneidiges Schwert — leicht OS-abhängig, schwer zu testen und es besteht Injektionsgefahr, wenn Argumente von Benutzereingaben stammen. Verwenden Sie es nur für interne Tools oder Verwaltungsskripte, vermeiden Sie es für primäre Geschäftslogik.

11. Häufige Fehler

  • rm -rf mit leerer Umgebungsvariablen ausführen — z.B. rm -rf $DIR/* wenn $DIR nicht gesetzt ist — löscht versehentlich das Root-Verzeichnis. Verwenden Sie immer set -u in Ihren Skripten oder überprüfen Sie die Variable vorher.
  • Vergessen von sudo, wenn Root-Rechte erforderlich sind, führt zu vagem Fehler Permission denied — überprüfen Sie mit ls -la, bevor Sie der App die Schuld geben.
  • Gewöhnheitsgemäß kill -9 verwenden verhindert, dass die Spring Boot-App den Connection-Pool rechtzeitig schließt und verursacht ein Leck in der Datenbank.
  • Pipe grep nach tail -f, vergessen Sie nicht --line-buffered — sonst denken Sie, das Log läuft nicht, aber es ist tatsächlich gepuffert.
  • chmod 777 ausführen, um schnell über Berechtigungsfehler hinauszukommen — das schafft eine Sicherheitslücke, besonders gefährlich für .env-Dateien oder SSH-Schlüssel.

12. Fazit

Die Befehle in diesem Artikel — find, grep, awk/sed, ps/kill, ss/curl, tar, tail -f, journalctl — sind ein minimaler Satz von Werkzeugen, damit Sie selbst debuggen können, ohne auf das DevOps-Team zu warten. Sie beherrschen sie nicht, indem Sie alle Flags auswendig lernen — Sie müssen nur wissen, welcher Befehl welches Problem löst und das Handbuch konsultieren, wenn Sie Details benötigen. Das Terminal ist immer noch das schnellste Debug-Tool, auch wenn Sie alle möglichen Grafana-, Kibana- oder APM-Tools haben.

linuxdevopsbashproductivityjava