Go 1.25 + capsh + Coverage: Warum plötzlich "go" im PATH fehlt
Nach dem Update auf Go 1.25 scheitert `go test -cover` unter capsh, weil der PATH beschnitten ist und Re-exec mehr PATH-Suche triggert. Fix: PATH setzen
- Schlagworte
- #Go #Toolchain #Coverage #Capsh #Sudo #Linux #Linuxbrew #ICMP #CAP_NET_RAW #Pro-Bing #Debugging
- veröffentlicht
- Lesezeit
- 3 Minuten
15.08.2025 · Notizen aus der Testhölle · Tools: Go 1.25.0, Linuxbrew, capsh, CAP_NET_RAW, pro-bing v0.7.0
TL;DR
Nach dem Update auf Go 1.25.0 schlugen meine Tests mit -cover in Paketen ohne eigene Tests fehl, wenn ich sie wegen ICMP mit capsh und CAP_NET_RAW starte. Ursache: sudo/capsh liefern einen beschnittenen PATH, während go test bei Coverage intern erneut Tools/go über den PATH aufruft. Fix: PATH beim Aufruf setzen.
Setup
Ich teste bei mein Online-Status-Test mit ICMP-Ping über:
- Modul:
github.com/prometheus-community/pro-bing v0.7.0 - Das braucht Root oder
CAP_NET_RAWfür „echten“ (icmp/privileged) Ping. - Deshalb rufe ich
go testviacapshauf:
sudo capsh --caps="cap_net_raw+ep" -- -c "/home/linuxbrew/.linuxbrew/bin/go test -cover ./..."
Das lief bis Go 1.24 problemlos.
Symptom nach Update auf Go 1.25.0
Mit -cover knallt es in Paketen ohne Tests:
github.com/AleksCee/dsl_test_go: exec: "go": executable file not found in $PATH
github.com/AleksCee/dsl_test_go/cmd: exec: "go": executable file not found in $PATH
github.com/AleksCee/dsl_test_go/database: exec: "go": executable file not found in $PATH
ok github.com/AleksCee/dsl_test_go/hosttest (cached) coverage: 50.9% of statements
ok github.com/AleksCee/dsl_test_go/mail (cached) coverage: 62.5% of statements
ok github.com/AleksCee/dsl_test_go/properties (cached) coverage: 93.8% of statements
ok github.com/AleksCee/dsl_test_go/version (cached) coverage: 100.0% of statements
Setze ich den PATH explizit, läuft es:
sudo capsh --caps="cap_net_raw+ep" -- -c 'PATH=/home/linuxbrew/.linuxbrew/bin:$PATH /home/linuxbrew/.linuxbrew/bin/go test -cover ./...'
Erwartbares Ergebnis (0.0 % für Pakete ohne Tests, Rest ok):
github.com/AleksCee/dsl_test_go coverage: 0.0% of statements
github.com/AleksCee/dsl_test_go/cmd coverage: 0.0% of statements
github.com/AleksCee/dsl_test_go/database coverage: 0.0% of statements
ok github.com/AleksCee/dsl_test_go/hosttest (cached) coverage: 50.9% of statements
ok github.com/AleksCee/dsl_test_go/mail (cached) coverage: 62.5% of statements
ok github.com/AleksCee/dsl_test_go/properties (cached) coverage: 93.8% of statements
ok github.com/AleksCee/dsl_test_go/version (cached) coverage: 100.0% of statements
Ohne Coverage ist sowieso alles gut:
sudo capsh --caps="cap_net_raw+ep" -- -c "/home/linuxbrew/.linuxbrew/bin/go test ./..."
Ausgabe:
? github.com/AleksCee/dsl_test_go [no test files]
? github.com/AleksCee/dsl_test_go/cmd [no test files]
? github.com/AleksCee/dsl_test_go/database [no test files]
ok github.com/AleksCee/dsl_test_go/hosttest (cached)
ok github.com/AleksCee/dsl_test_go/mail (cached)
ok github.com/AleksCee/dsl_test_go/properties (cached)
ok github.com/AleksCee/dsl_test_go/version (cached)
Was da wirklich passiert (Arbeitsthese)
sudo&secure_path: Untersudo/capshist häufig ein restriktiverPATHaktiv./home/linuxbrew/.linuxbrew/binfehlt dann.- Re-exec bei Coverage: Seit den neueren Toolchain-Mechaniken ruft
go testintern zusätzliche Tools (oder sogargoselbst) über den Namen auf. Das triggert PATH-Suche. - Spezialeffekt bei
-coverohne Tests: Auch wenn ein Paket keine Tests hat, verursacht-coverzusätzliche interne Schritte. Ohne passendenPATHfindet der Subprozess keingo→exec: "go": not found.
Kurz: Der erste go-Start klappt dank absolutem Pfad, Folgeprozesse stolpern über den beschnittenen PATH.
Lösungswege
1) PATH beim Aufruf setzen (sofort, pragmatisch)
sudo capsh --caps="cap_net_raw+ep" -- -c 'PATH=/home/linuxbrew/.linuxbrew/bin:$PATH /home/linuxbrew/.linuxbrew/bin/go test -cover ./...'
Im Makefile:
GOBINPATH=$(shell which go)
CAPSH_PATH=$(shell dirname $(shell which go)):$(PATH)
...
test:
@sudo capsh --caps="cap_net_raw+ep" -- -c 'PATH=$(CAPSH_PATH) $(GOBINPATH) test -v -cover ./...'
2) Ping ohne Root? Ja, aber…
pro-bing kann unprivilegiert im UDP-Modus, liefert bei mir aber ungenauere Ergebnisse. Für „echtes“ ICMP bleibe ich bei capsh + CAP_NET_RAW.
Fazit
Kein Bug in pro-bing, kein reines capsh-Thema, sondern ein Timing zwischen Coverage-Re-exec und beschnittenem PATH unter sudo.
Mit einem gesetzten PATH ist die Welt wieder gerade. Ping bleibt privilegiert, Tests bleiben grün, und go bleibt im PATH, wo es hingehört.