fix(agent/windows): named pipe Tailscale + hideWindow + logs

- Use Windows named pipe \.\pipe\studioe5-tailscaled instead of Unix socket
- Apply hideWindow to all child processes (tailscale, podman, docker, browser)
- Redirect agent logs to <data-dir>/agent.log and tailscaled logs to tailscaled.log
- Fix double tailscale/ tailscale dir path in startTailscaleAndReport
- Remove --operator=root on Windows
- Bump agent version to 0.3.1
This commit is contained in:
EduBox Dev
2026-06-23 18:18:26 +00:00
parent 03b2f1267d
commit d090f67bff
10 changed files with 121 additions and 37 deletions
+37 -16
View File
@@ -61,17 +61,29 @@ func startTailscale(dataDir, nodeID, headscaleURL, authKey string) (string, erro
if err := os.MkdirAll(tsDataDir, 0700); err != nil {
return "", fmt.Errorf("create tailscale dir: %w", err)
}
tsSocket = filepath.Join(tsDataDir, "tailscaled.sock")
if runtime.GOOS == "windows" {
// Windows uses named pipes for tailscaled IPC, not Unix sockets.
tsSocket = `\\.\pipe\studioe5-tailscaled`
} else {
tsSocket = filepath.Join(tsDataDir, "tailscaled.sock")
}
stateFile := filepath.Join(tsDataDir, "tailscaled.state")
log.Printf("Starting tailscaled for node %s", nodeID)
log.Printf("Starting tailscaled for node %s (socket=%s)", nodeID, tsSocket)
tsCmd = exec.Command(tailscaleBin("tailscaled"),
"--state="+stateFile,
"--socket="+tsSocket,
"--tun=userspace-networking",
)
tsCmd.Stdout = os.Stdout
tsCmd.Stderr = os.Stderr
hideWindow(tsCmd)
// Redirect tailscaled output to a dedicated log file.
tsLogPath := filepath.Join(tsDataDir, "tailscaled.log")
if tsLogFile, err := os.OpenFile(tsLogPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644); err == nil {
tsCmd.Stdout = tsLogFile
tsCmd.Stderr = tsLogFile
} else {
log.Printf("Cannot open tailscaled log file %s: %v", tsLogPath, err)
}
if err := tsCmd.Start(); err != nil {
tsCmd = nil
return "", fmt.Errorf("start tailscaled: %w", err)
@@ -84,17 +96,22 @@ func startTailscale(dataDir, nodeID, headscaleURL, authKey string) (string, erro
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
upCmd := exec.CommandContext(ctx, tailscaleBin("tailscale"),
"--socket="+tsSocket,
upArgs := []string{
"--socket=" + tsSocket,
"up",
"--authkey="+authKey,
"--login-server="+headscaleURL,
"--hostname="+nodeID,
"--authkey=" + authKey,
"--login-server=" + headscaleURL,
"--hostname=" + nodeID,
"--accept-dns=false",
"--operator=root",
)
upCmd.Stdout = os.Stdout
upCmd.Stderr = os.Stderr
}
if runtime.GOOS != "windows" {
// --operator is only meaningful on Unix systems.
upArgs = append(upArgs, "--operator=root")
}
upCmd := exec.CommandContext(ctx, tailscaleBin("tailscale"), upArgs...)
hideWindow(upCmd)
upCmd.Stdout = log.Writer()
upCmd.Stderr = log.Writer()
if err := upCmd.Run(); err != nil {
_ = tsCmd.Process.Kill()
_ = tsCmd.Wait()
@@ -104,10 +121,12 @@ func startTailscale(dataDir, nodeID, headscaleURL, authKey string) (string, erro
// Wait for an IP address.
for {
out, err := exec.CommandContext(ctx, tailscaleBin("tailscale"),
statusCmd := exec.CommandContext(ctx, tailscaleBin("tailscale"),
"--socket="+tsSocket,
"status", "--json",
).Output()
)
hideWindow(statusCmd)
out, err := statusCmd.Output()
if err != nil {
select {
case <-ctx.Done():
@@ -151,7 +170,9 @@ func stopTailscaleLocked() {
return
}
if tsSocket != "" {
_ = exec.Command(tailscaleBin("tailscale"), "--socket="+tsSocket, "down").Run()
downCmd := exec.Command(tailscaleBin("tailscale"), "--socket="+tsSocket, "down")
hideWindow(downCmd)
_ = downCmd.Run()
}
_ = tsCmd.Process.Kill()
_ = tsCmd.Wait()