You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
3.4 KiB
113 lines
3.4 KiB
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
func isAutoStartEnabled(appPath string) bool {
|
|
serviceFile := autoStartServiceFile(appPath)
|
|
kioskInfof("autostart check begin service=%s expectedExec=%s expectedWorkdir=%s", serviceFile, appPath, filepath.Dir(appPath))
|
|
|
|
content, err := os.ReadFile(serviceFile)
|
|
if err != nil {
|
|
kioskWarnf("autostart service read failed service=%s err=%v", serviceFile, err)
|
|
return false
|
|
}
|
|
matches := autoStartServiceMatches(string(content), appPath)
|
|
kioskInfof("autostart service match result service=%s matches=%v", serviceFile, matches)
|
|
return matches
|
|
}
|
|
|
|
func enableAutoStart(appPath string) error {
|
|
serviceFile := autoStartServiceFile(appPath)
|
|
kioskInfof("autostart setup begin service=%s exec=%s workdir=%s", serviceFile, appPath, filepath.Dir(appPath))
|
|
|
|
content := autoStartServiceContent(appPath)
|
|
kioskDebugf("autostart service content:\n%s", content)
|
|
cmd := exec.Command("sudo", "bash", "-c",
|
|
fmt.Sprintf("echo '%s' > %s", content, serviceFile))
|
|
if err := cmd.Run(); err != nil {
|
|
kioskErrorf("write autostart service failed service=%s err=%v", serviceFile, err)
|
|
return err
|
|
}
|
|
kioskInfof("write autostart service success service=%s", serviceFile)
|
|
|
|
cmd = exec.Command("sudo", "systemctl", "daemon-reload")
|
|
if err := cmd.Run(); err != nil {
|
|
kioskErrorf("systemctl daemon-reload failed err=%v", err)
|
|
return err
|
|
}
|
|
kioskInfof("systemctl daemon-reload success")
|
|
|
|
cmd = exec.Command("sudo", "systemctl", "enable", autoStartServiceName(appPath))
|
|
if err := cmd.Run(); err != nil {
|
|
kioskErrorf("systemctl enable failed service=%s err=%v", autoStartServiceName(appPath), err)
|
|
return err
|
|
}
|
|
kioskInfof("systemctl enable success service=%s", autoStartServiceName(appPath))
|
|
return nil
|
|
}
|
|
|
|
func autoStartServiceName(appPath string) string {
|
|
return strings.TrimSuffix(filepath.Base(appPath), filepath.Ext(appPath)) + ".service"
|
|
}
|
|
|
|
func autoStartServiceFile(appPath string) string {
|
|
return filepath.Join("/etc/systemd/system", autoStartServiceName(appPath))
|
|
}
|
|
|
|
func autoStartServiceContent(appPath string) string {
|
|
appName := strings.TrimSuffix(filepath.Base(appPath), filepath.Ext(appPath))
|
|
return fmt.Sprintf(`[Unit]
|
|
Description=%s Background Service
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStart=%s
|
|
Restart=on-failure
|
|
RestartSec=10
|
|
User=root
|
|
WorkingDirectory=%s
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
`,
|
|
appName,
|
|
appPath,
|
|
filepath.Dir(appPath))
|
|
}
|
|
|
|
func autoStartServiceMatches(content string, appPath string) bool {
|
|
execStart := normalizeSystemdValue(systemdUnitValue(content, "ExecStart"))
|
|
workingDirectory := normalizeSystemdValue(systemdUnitValue(content, "WorkingDirectory"))
|
|
expectedWorkdir := filepath.Dir(appPath)
|
|
matches := execStart == appPath && workingDirectory == expectedWorkdir
|
|
kioskInfof("autostart service fields execStart=%s expectedExec=%s workingDirectory=%s expectedWorkdir=%s matches=%v", execStart, appPath, workingDirectory, expectedWorkdir, matches)
|
|
|
|
return matches
|
|
}
|
|
|
|
func systemdUnitValue(content string, key string) string {
|
|
for _, line := range strings.Split(content, "\n") {
|
|
line = strings.TrimSpace(line)
|
|
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") {
|
|
continue
|
|
}
|
|
name, value, ok := strings.Cut(line, "=")
|
|
if !ok || strings.TrimSpace(name) != key {
|
|
continue
|
|
}
|
|
return strings.TrimSpace(value)
|
|
}
|
|
return ""
|
|
}
|
|
|
|
func normalizeSystemdValue(value string) string {
|
|
return strings.Trim(strings.TrimSpace(value), `"'`)
|
|
}
|