package app import ( "fmt" "os" "os/exec" "strings" "time" ) func transportWrapExecWithNetns(client TransportClient, command string) string { cmd := strings.TrimSpace(command) if cmd == "" || !transportNetnsEnabled(client) { return cmd } ns := transportNetnsName(client) if ns == "" { return cmd } name, args, err := transportNetnsExecCommand(client, ns, "/bin/sh", "-lc", cmd) if err != nil { return cmd } return shellJoinArgs(append([]string{name}, args...)) } func transportResolveNetnsNsenterBin(client TransportClient) string { if explicit := strings.TrimSpace(transportConfigString(client.Config, "netns_nsenter_bin")); explicit != "" { return explicit } if p, err := exec.LookPath("nsenter"); err == nil { return strings.TrimSpace(p) } candidates := []string{ "/usr/bin/nsenter", "/bin/nsenter", "/usr/sbin/nsenter", "/sbin/nsenter", } for _, cand := range candidates { if _, err := os.Stat(cand); err == nil { return cand } } return "" } func transportNetnsExecCommand(client TransportClient, ns string, command ...string) (string, []string, error) { if strings.TrimSpace(ns) == "" { return "", nil, fmt.Errorf("netns name is empty") } if len(command) == 0 { return "", nil, fmt.Errorf("netns command is empty") } mode := strings.ToLower(strings.TrimSpace(transportConfigString(client.Config, "netns_exec_mode"))) useNsenter := false switch mode { case "ip", "ip-netns", "ip_netns": useNsenter = false case "nsenter": useNsenter = true case "", "auto": useNsenter = true default: useNsenter = true } if useNsenter { if bin := transportResolveNetnsNsenterBin(client); bin != "" { args := []string{"--net=/var/run/netns/" + ns, "--"} args = append(args, command...) return bin, args, nil } } ipBin := strings.TrimSpace(transportConfigString(client.Config, "netns_ip_bin")) if ipBin == "" { ipBin = "ip" } args := []string{"netns", "exec", ns} args = append(args, command...) return ipBin, args, nil } func transportRunInNetnsMust(timeout time.Duration, client TransportClient, ns string, command ...string) error { name, args, err := transportNetnsExecCommand(client, ns, command...) if err != nil { return err } return transportRunMust(timeout, name, args...) } func transportRunInNetnsSoft(timeout time.Duration, client TransportClient, ns string, command ...string) error { name, args, err := transportNetnsExecCommand(client, ns, command...) if err != nil { return err } return transportRunSoft(timeout, name, args...) }