
CLI-Tool zum Inspizieren und Verwalten von Diensten, die auf Localhost-Ports lauschen.
███████╗ ██████╗ ███╗ ██╗ █████╗ ██████╗
██╔════╝██╔═══██╗████╗ ██║██╔══██╗██╔══██╗
███████╗██║ ██║██╔██╗ ██║███████║██████╔╝
╚════██║██║ ██║██║╚██╗██║██╔══██║██╔══██╗
███████║╚██████╔╝██║ ╚████║██║ ██║██║ ██║
╚══════╝ ╚═════╝ ╚═╝ ╚═══╝╚═╝ ╚═╝╚═╝ ╚═╝
Wisse, was auf deinem Rechner läuft.
Ich hatte die Nase voll davon, jedes Mal lsof -iTCP -sTCP:LISTEN | grep ... auszuführen, wenn ein Port bereits belegt war, und dann noch eine Minute herauszufinden, ob es sich um einen Docker-Container oder einen verwaisten Dev-Server aus einem anderen Worktree handelte. Also habe ich sonar gebaut.
Es zeigt alles, was auf localhost lauscht, mit Docker-Containernamen, Compose-Projekten, Ressourcennutzung und anklickbaren URLs. Du kannst Prozesse beenden, Logs anzeigen, in Container einsteigen und mehr – alles über die Portnummer.
$ sonar list
PORT PROCESS CONTAINER IMAGE CPORT URL
1780 proxy (traefik:3.0) my-app-proxy-1 traefik:3.0 80 http://localhost:1780
3000 next-server (v16.1.6) http://localhost:3000
5432 db (postgres:17) my-app-db-1 postgres:17 5432 http://localhost:5432
6873 frontend (frontend:latest) my-app-frontend-1 frontend:latest 5173 http://localhost:6873
9700 backend (backend:latest) my-app-backend-1 backend:latest 8000 http://localhost:9700
5 Ports (4 Docker, 1 User)
brew install raskrebs/sonar/sonar
Unter macOS wird dabei auch die Menüleisten-App sonar-tray installiert.
curl -sfL https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.sh | bash
Lädt die neueste Binärdatei nach ~/.local/bin herunter und fügt sie bei Bedarf zu deinem PATH hinzu. Starte dein Terminal neu oder führe source ~/.zshrc aus.
Unter Windows (PowerShell):
irm https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.ps1 | iex
Benutzerdefinierter Installationsort:
curl -sfL https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.sh | SONAR_INSTALL_DIR=/usr/local/bin bash
Installation einer bestimmten Version:
curl -sfL https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.sh | SONAR_VERSION=vX.Y.Z bash
$env:SONAR_VERSION="vX.Y.Z"; irm https://raw.githubusercontent.com/raskrebs/sonar/main/scripts/install.ps1 | iex
go install github.com/raskrebs/sonar@latest
Hinweis:
go installinstalliert nur die CLI. Die Menüleisten-Tray-App (sonar tray) ist ein natives Swift-Binary und muss separat gebaut werden – siehe Tray-App unten.
Shell-Komplettierungen (Tab-Vervollständigung für Portnummern):
sonar completion zsh > "${fpath[1]}/_sonar" # zsh
sonar completion bash > /etc/bash_completion.d/sonar # bash
sonar completion fish | source # fish
sonar list # alle Ports anzeigen
sonar list --stats # inklusive CPU, Arbeitsspeicher, Zustand, Laufzeit
sonar list --filter docker # nur Docker-Ports
sonar list --sort name # nach Prozessname sortieren
sonar list --json # JSON-Ausgabe
sonar list -a # Desktop-Apps einschließen
sonar list -c port,cpu,mem,uptime,state # benutzerdefinierte Spalten
sonar list --health # HTTP-Health-Checks ausführen
sonar list --host user@server # entfernten Rechner via SSH scannen
Standardmäßig blendet sonar Desktop-Apps und Systemdienste aus, die auf TCP-Ports lauschen, aber für die Entwicklung nicht relevant sind – also Dinge wie Figma, Discord, Spotify, ControlCenter, AirPlay und andere macOS-.app-Bundles und /System/Library/-Daemons. Verwende -a, um sie einzuschließen.
Verfügbare Spalten: port, process, pid, type, url, cpu, mem, threads, uptime, state, connections, health, latency, container, image, containerport, compose, project, user, bind, ip
sonar info 3000
Zeigt alles über einen Port: vollständigen Befehl, Benutzer, Bind-Addresse, CPU/Arbeitsspeicher/Threads, Laufzeit, Health-Check-Ergebnis und Docker-Details, falls zutreffend.
sonar kill 3000 # SIGTERM
sonar kill 3000 -f # SIGKILL
sonar kill-all --filter docker # alle Docker-Container stoppen
sonar kill-all --project my-app # ein Compose-Projekt stoppen
sonar kill-all --filter user -y # Bestätigung überspringen
Docker-Container werden mit docker stop gestoppt, nicht durch Senden von Signalen.
sonar logs 3000
Für Docker-Container führt es docker logs -f aus. Für native Prozesse findet es Logdateien via lsof und zeigt sie an. Fallback auf macOS log stream oder Linux /proc/<pid>/fd.
sonar attach 3000 # Shell in Docker-Container oder TCP-Verbindung
sonar attach 3000 --shell bash # bestimmte Shell
sonar watch # alle 2s abfragen, Unterschiede anzeigen
sonar watch --stats # Live-Ressourcenstatistiken (wie docker stats)
sonar watch -i 500ms # schnellere Abfrage
sonar watch --notify # Desktop-Benachrichtigungen bei Port-Änderungen
sonar watch --host user@server # entfernten Rechner überwachen
sonar graph # anzeigen, welche Dienste miteinander kommunizieren
sonar graph --json # strukturierte Ausgabe
sonar graph --dot # Graphviz-DOT-Format
Zeigt etablierte Verbindungen zwischen lauschenden Ports (z. B. dein Backend, das sich mit Postgres verbindet).
Speichere eine Reihe erwarteter Ports für ein Projekt und prüfe dann, ob alle laufen, oder fahre sie herunter:
sonar profile create my-app # aktuellen Port-Snapshot erstellen
sonar profile list # gespeicherte Profile anzeigen
sonar profile show my-app # Profildetails anzeigen
sonar up my-app # prüfen, welche erwarteten Ports laufen
sonar down my-app # alle Ports im Profil stoppen
sonar wait 5432 # blockieren, bis Port Verbindungen akzeptiert
sonar wait 5432 3000 6379 # auf mehrere Ports warten
sonar wait 5432 --timeout 30s # nach 30 Sekunden fehlschlagen
sonar wait 5432 --http # auf HTTP 200 warten, nicht nur TCP offen
sonar wait 5432 --http=/health # bestimmten Endpunkt prüfen
sonar wait 5432 -i 500ms # benutzerdefiniertes Abfrageintervall
sonar wait 5432 -q # keine Ausgabe, nur Exit-Code (für Skripte)
Nützlich für Skripte rund um docker compose up -d oder Hintergrunddienste. Das --http-Flag wartet auf eine tatsächliche HTTP-200-399-Antwort, nicht nur auf einen TCP-Socket, was Dienste abfängt, die Verbindungen annehmen, bevor sie wirklich bereit sind. Verwende --http=/health, um einen bestimmten Endpunkt zu prüfen. Exit-Codes: 0 (bereit), 1 (Timeout), 2 (unterbrochen).
docker compose up -d
sonar wait 5432 3000 --timeout 60s && npm run migrate && npm run test
sonar map 6873 3002
Leitet Datenverkehr weiter, sodass der Dienst auf Port 6873 auch auf Port 3002 verfügbar ist.
sonar next # erster freier Port ab 3000
sonar next 8000 # erster freier Port ab 8000
sonar next 3000-3100 # erster freier Port im Bereich
sonar next -n 3 # 3 aufeinander folgende freie Ports
sonar next --json # JSON-Ausgabe
sonar open 3000 # im Browser öffnen
sonar tray # Menüleisten-App mit Live-Statistiken (macOS)
sonar --no-color # Farben deaktivieren (respektiert auch NO_COLOR-Umgebungsvariable)
Das --stats-Flag holt prozess- und containerbezogene Ressourcennutzung. Für Docker-Container verwendet es die Docker-Engine-API für genaue Metriken pro Container. Ohne --stats gibt sonar sofort Ergebnisse zurück.
sonar liest optionale Standardwerte aus ~/.config/sonar/config.yaml. Die Datei ist
optional – ohne sie gelten integrierte Standardwerte. Befehlszeilenflags überschreiben
die Konfigurationsdatei immer.
Erstelle eine Startdatei:
sonar config init # kommentierte Vorlage schreiben
sonar config path # Dateipfad ausgeben
sonar config edit # in $EDITOR öffnen
Beispielkonfiguration:
list:
columns: [port, process, container, image, containerport, url]
sort: port # port | pid | name | type
filter: "" # docker | user | system | "" (alle)
all: false # Desktop-Apps standardmäßig einschließen
color: true # auf false setzen, um Farbausgabe zu deaktivieren
services: # benutzerdefinierte/unbekannte Ports beschriften
9000: php-fpm
5050: my-dashboard
Ungültige Werte werden mit einer Warnung ignoriert; sonar fährt mit den Standardwerten fort.
Die Menüleisten-Tray-App (nur macOS) ist ein natives Swift-Binary, das Live-Port-Statistiken in deiner Menüleiste anzeigt. Wenn du sonar über das Installationsskript oder eine GitHub-Release installiert hast, ist das Tray-Binary (sonar-tray) automatisch enthalten.
Wenn du über go install installiert hast, baue es manuell:
swiftc -O -o sonar-tray tray/SonarTray.swift -target arm64-apple-macos13
Verschiebe dann sonar-tray an einen Ort in deinem $PATH und führe aus:
sonar tray
lsof)ss)netstat)Danke an alle, die zu sonar beigetragen haben!