„Address already in use" – herausfinden, wer den Port belegt
Der Entwicklungsserver startet nicht, weil Port 8000 angeblich schon benutzt wird – meistens von einem eigenen Prozess von vorhin. Mit ss oder lsof findest du ihn in Sekunden, statt das Terminal neu zu starten.
Man kennt die Meldung:
Failed to listen on 0.0.0.0:8000 (reason: Address already in use)Fast immer ist es ein eigener Prozess von vorhin, der im Hintergrund weiterläuft. Die üblichen Reaktionen — Terminal neu starten, Rechner neu starten, einen anderen Port nehmen — funktionieren, sind aber unnötig.
Wer hört auf dem Port? (Linux)
ss -tulpn | grep :8000Die Buchstaben stehen für: tcp, udp, listening, process, numerisch (also Portnummern statt Dienstnamen). Die Ausgabe endet mit etwas wie:
users:(("php",pid=3831,fd=4))Da steht alles Nötige: Programm und Prozess-ID.
Oder mit lsof (Linux und macOS)
lsof -i :8000lsof gibt es auf beiden Systemen und die Ausgabe ist etwas leserlicher — dafür ist es oft nicht vorinstalliert. Auf macOS ist es der übliche Weg, weil ss dort fehlt.
Wenn du nur die PID willst:
lsof -ti :8000 # gibt ausschließlich die Prozess-ID ausBeenden
kill 3831 # höflich: bitte aufräumen und beenden
kill -9 3831 # notfalls: sofort abschießenZuerst immer das normale kill. Damit bekommt der Prozess die Chance, Dateien zu schließen und aufzuräumen. -9 lässt ihm keine — bei einem Entwicklungsserver egal, bei einer Datenbank keine gute Idee.
In einem Rutsch:
kill "$(lsof -ti :8000)"Das nehme ich nur, wenn ich vorher gesehen habe, was dort läuft. Blind alles zu beenden, was auf einem Port lauscht, ist genau die Sorte Einzeiler, die man irgendwann versehentlich auf dem falschen Rechner ausführt.
Und wenn gar kein Prozess auftaucht?
Dann gibt es zwei häufige Erklärungen:
- Der Prozess gehört einem anderen Nutzer.
ssundlsofzeigen fremde Prozesse nur mit erhöhten Rechten — probier es mitsudo. - Der Port hängt im Zustand
TIME_WAIT. Nach dem Beenden eines Servers bleibt die Verbindung noch kurz reserviert, damit verspätete Pakete nicht in eine neue Verbindung platzen. Das löst sich nach ein paar Sekunden bis zwei Minuten von selbst. Sichtbar wird es mit:
ss -tan | grep :8000Was ich mir angewöhnt habe
Entwicklungsserver starte ich in einem eigenen Terminal und beende sie dort auch wieder, statt sie in den Hintergrund zu schicken und zu vergessen. Wenn ich sie doch im Hintergrund brauche, schreibe ich die PID in eine Datei:
php -S 127.0.0.1:8000 & echo $! > .server.pid
kill "$(cat .server.pid)" && rm .server.pidDann muss man nie suchen. Aber wenn doch: ss -tulpn | grep :PORT ist der Befehl, den ich am häufigsten aus meinem Verlauf hole.
Du kämpfst öfter mit einer lokalen Entwicklungsumgebung, die nicht so will? Manchmal ist es eine Kleinigkeit, manchmal die Einrichtung. Frag mich.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
Zwei Listen vergleichen mit comm – wer fehlt, wer ist neu, wer ist in beiden
Welche Dateien fehlen im Backup? Welche Kunden aus der alten Liste stehen nicht in der neuen? Für genau diese Fragen gibt es seit Unix-Urzeiten ein Werkzeug, das kaum jemand kennt – comm vergleicht zwei sortierte Listen und sagt dir in einer Zeile, was nur links, nur rechts oder in beiden steht.
Warum deine Zählvariable nach der Schleife wieder 0 ist – Prozess-Substitution in Bash
Ein Klassiker, der jeden einmal erwischt: Du zählst in einer while-Schleife hoch, und hinterher steht die Variable trotzdem auf 0. Schuld ist eine Subshell hinter der Pipe. Mit Prozess-Substitution behältst du das Ergebnis – und kannst nebenbei zwei Befehle direkt vergleichen.
Pfade und Namen zerlegen — ganz ohne basename, dirname und sed
Die Shell kann Zeichenketten selbst zerschneiden. Kein Aufruf eines externen Programms, keine Pipe – nur geschweifte Klammern. Wenn du das einmal kennst, werden deine Skripte kürzer und deutlich schneller.