91 lines
2.6 KiB
Go
91 lines
2.6 KiB
Go
package app
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
func transportSystemdRunActionUnits(
|
|
client TransportClient,
|
|
action string,
|
|
units []string,
|
|
aggOut *[]string,
|
|
aggErr *[]string,
|
|
) *transportBackendActionResult {
|
|
for _, unit := range units {
|
|
stdout, stderr, exitCode, err := transportRunCommand(transportBackendActionTimeout, "systemctl", action, unit)
|
|
if s := strings.TrimSpace(stdout); s != "" {
|
|
*aggOut = append(*aggOut, unit+": "+s)
|
|
}
|
|
if s := strings.TrimSpace(stderr); s != "" {
|
|
*aggErr = append(*aggErr, unit+": "+s)
|
|
}
|
|
if (action == "start" || action == "restart") &&
|
|
client.Kind == TransportClientSingBox &&
|
|
transportSystemdUnitMissingError(stdout, stderr, exitCode, err) {
|
|
appendTraceLineRateLimited(
|
|
"transport",
|
|
fmt.Sprintf("systemctl %s unit missing, trying auto-provision: client=%s unit=%s", action, client.ID, unit),
|
|
20*time.Second,
|
|
)
|
|
provision := (transportSystemdBackend{}).Provision(client)
|
|
if s := strings.TrimSpace(provision.Stdout); s != "" {
|
|
*aggOut = append(*aggOut, "provision: "+s)
|
|
}
|
|
if s := strings.TrimSpace(provision.Stderr); s != "" {
|
|
*aggErr = append(*aggErr, "provision: "+s)
|
|
}
|
|
if !provision.OK {
|
|
msg := strings.TrimSpace(provision.Message)
|
|
if msg == "" {
|
|
msg = "auto-provision failed"
|
|
}
|
|
return &transportBackendActionResult{
|
|
OK: false,
|
|
Code: provision.Code,
|
|
Message: msg,
|
|
ExitCode: provision.ExitCode,
|
|
Stdout: strings.Join(*aggOut, "\n"),
|
|
Stderr: strings.Join(*aggErr, "\n"),
|
|
Retryable: true,
|
|
}
|
|
}
|
|
stdout, stderr, exitCode, err = transportRunCommand(transportBackendActionTimeout, "systemctl", action, unit)
|
|
if s := strings.TrimSpace(stdout); s != "" {
|
|
*aggOut = append(*aggOut, unit+": "+s)
|
|
}
|
|
if s := strings.TrimSpace(stderr); s != "" {
|
|
*aggErr = append(*aggErr, unit+": "+s)
|
|
}
|
|
}
|
|
if action == "stop" && transportSystemdStopMissingUnitNoop(stdout, stderr, exitCode, err) {
|
|
appendTraceLineRateLimited(
|
|
"transport",
|
|
fmt.Sprintf("systemctl stop noop: client=%s unit=%s reason=unit-missing", client.ID, unit),
|
|
15*time.Second,
|
|
)
|
|
continue
|
|
}
|
|
if err != nil || exitCode != 0 {
|
|
msg := strings.TrimSpace(stderr)
|
|
if msg == "" {
|
|
msg = strings.TrimSpace(stdout)
|
|
}
|
|
if msg == "" {
|
|
msg = fmt.Sprintf("systemctl %s %s failed", action, unit)
|
|
}
|
|
return &transportBackendActionResult{
|
|
OK: false,
|
|
Code: "TRANSPORT_BACKEND_ACTION_FAILED",
|
|
Message: msg,
|
|
ExitCode: exitCode,
|
|
Stdout: strings.Join(*aggOut, "\n"),
|
|
Stderr: strings.Join(*aggErr, "\n"),
|
|
Retryable: action != "stop",
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|