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_RAW
für „echten“ (icmp/privileged) Ping. - Deshalb rufe ich
go test
viacapsh
auf:
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
/capsh
ist häufig ein restriktiverPATH
aktiv./home/linuxbrew/.linuxbrew/bin
fehlt dann.- Re-exec bei Coverage: Seit den neueren Toolchain-Mechaniken ruft
go test
intern zusätzliche Tools (oder sogargo
selbst) über den Namen auf. Das triggert PATH-Suche. - Spezialeffekt bei
-cover
ohne Tests: Auch wenn ein Paket keine Tests hat, verursacht-cover
zusätzliche interne Schritte. Ohne passendenPATH
findet 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.