mirror of
https://gitee.com/wanwujie/sub2api
synced 2026-04-04 23:42:13 +08:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e81e395b3 | ||
|
|
f0e89992f7 | ||
|
|
4eaa0cf14a |
@@ -1,44 +1,39 @@
|
||||
package sysutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"os/exec"
|
||||
"os"
|
||||
"runtime"
|
||||
"time"
|
||||
)
|
||||
|
||||
const serviceName = "sub2api"
|
||||
|
||||
// RestartService triggers a service restart via systemd.
|
||||
// RestartService triggers a service restart by gracefully exiting.
|
||||
//
|
||||
// IMPORTANT: This function initiates the restart and returns immediately.
|
||||
// The actual restart happens asynchronously - the current process will be killed
|
||||
// by systemd and a new process will be started.
|
||||
//
|
||||
// We use Start() instead of Run() because:
|
||||
// - systemctl restart will kill the current process first
|
||||
// - Run() waits for completion, but the process dies before completion
|
||||
// - Start() spawns the command independently, allowing systemd to handle the full cycle
|
||||
// This relies on systemd's Restart=always configuration to automatically
|
||||
// restart the service after it exits. This is the industry-standard approach:
|
||||
// - Simple and reliable
|
||||
// - No sudo permissions needed
|
||||
// - No complex process management
|
||||
// - Leverages systemd's native restart capability
|
||||
//
|
||||
// Prerequisites:
|
||||
// - Linux OS with systemd
|
||||
// - NOPASSWD sudo access configured (install.sh creates /etc/sudoers.d/sub2api)
|
||||
// - Service configured with Restart=always in systemd unit file
|
||||
func RestartService() error {
|
||||
if runtime.GOOS != "linux" {
|
||||
return fmt.Errorf("systemd restart only available on Linux")
|
||||
log.Println("Service restart via exit only works on Linux with systemd")
|
||||
return nil
|
||||
}
|
||||
|
||||
log.Println("Initiating service restart...")
|
||||
log.Println("Initiating service restart by graceful exit...")
|
||||
log.Println("systemd will automatically restart the service (Restart=always)")
|
||||
|
||||
// The sub2api user has NOPASSWD sudo access for systemctl commands
|
||||
// (configured by install.sh in /etc/sudoers.d/sub2api).
|
||||
// Use -n (non-interactive) to prevent sudo from waiting for password input
|
||||
cmd := exec.Command("sudo", "-n", "systemctl", "restart", serviceName)
|
||||
if err := cmd.Start(); err != nil {
|
||||
return fmt.Errorf("failed to initiate service restart: %w", err)
|
||||
}
|
||||
// Give a moment for logs to flush and response to be sent
|
||||
go func() {
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
log.Println("Service restart initiated successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -73,9 +73,6 @@ declare -A MSG_ZH=(
|
||||
["dirs_configured"]="目录配置完成"
|
||||
["installing_service"]="正在安装 systemd 服务..."
|
||||
["service_installed"]="systemd 服务已安装"
|
||||
["setting_up_sudoers"]="正在配置 sudoers..."
|
||||
["sudoers_configured"]="sudoers 配置完成"
|
||||
["sudoers_failed"]="sudoers 验证失败,已移除文件"
|
||||
["ready_for_setup"]="准备就绪,可以启动设置向导"
|
||||
|
||||
# Completion
|
||||
@@ -173,9 +170,6 @@ declare -A MSG_EN=(
|
||||
["dirs_configured"]="Directories configured"
|
||||
["installing_service"]="Installing systemd service..."
|
||||
["service_installed"]="Systemd service installed"
|
||||
["setting_up_sudoers"]="Setting up sudoers..."
|
||||
["sudoers_configured"]="Sudoers configured"
|
||||
["sudoers_failed"]="Sudoers validation failed, removing file"
|
||||
["ready_for_setup"]="Ready for Setup Wizard"
|
||||
|
||||
# Completion
|
||||
@@ -521,35 +515,6 @@ setup_directories() {
|
||||
print_success "$(msg 'dirs_configured')"
|
||||
}
|
||||
|
||||
# Setup sudoers for service restart
|
||||
setup_sudoers() {
|
||||
print_info "$(msg 'setting_up_sudoers')"
|
||||
|
||||
# Always generate sudoers file from script (not from tar.gz)
|
||||
# This ensures the latest configuration is used even with older releases
|
||||
# Support both /bin/systemctl and /usr/bin/systemctl for different distros
|
||||
cat > /etc/sudoers.d/sub2api << 'EOF'
|
||||
# Sudoers configuration for Sub2API
|
||||
sub2api ALL=(ALL) NOPASSWD: /bin/systemctl restart sub2api
|
||||
sub2api ALL=(ALL) NOPASSWD: /bin/systemctl stop sub2api
|
||||
sub2api ALL=(ALL) NOPASSWD: /bin/systemctl start sub2api
|
||||
sub2api ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart sub2api
|
||||
sub2api ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop sub2api
|
||||
sub2api ALL=(ALL) NOPASSWD: /usr/bin/systemctl start sub2api
|
||||
EOF
|
||||
|
||||
# Set correct permissions (required for sudoers files)
|
||||
chmod 440 /etc/sudoers.d/sub2api
|
||||
|
||||
# Validate sudoers file
|
||||
if visudo -c -f /etc/sudoers.d/sub2api &>/dev/null; then
|
||||
print_success "$(msg 'sudoers_configured')"
|
||||
else
|
||||
print_warning "$(msg 'sudoers_failed')"
|
||||
rm -f /etc/sudoers.d/sub2api
|
||||
fi
|
||||
}
|
||||
|
||||
# Install systemd service
|
||||
install_service() {
|
||||
print_info "$(msg 'installing_service')"
|
||||
@@ -716,7 +681,6 @@ uninstall() {
|
||||
|
||||
print_info "$(msg 'removing_files')"
|
||||
rm -f /etc/systemd/system/sub2api.service
|
||||
rm -f /etc/sudoers.d/sub2api
|
||||
systemctl daemon-reload
|
||||
|
||||
print_info "$(msg 'removing_install_dir')"
|
||||
@@ -787,7 +751,6 @@ main() {
|
||||
create_user
|
||||
setup_directories
|
||||
install_service
|
||||
setup_sudoers
|
||||
prepare_for_setup
|
||||
print_completion
|
||||
}
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
# Sudoers configuration for Sub2API
|
||||
# This file allows the sub2api service user to restart the service without password
|
||||
#
|
||||
# Installation:
|
||||
# sudo cp sub2api-sudoers /etc/sudoers.d/sub2api
|
||||
# sudo chmod 440 /etc/sudoers.d/sub2api
|
||||
#
|
||||
# SECURITY NOTE: This grants limited sudo access only for service management
|
||||
|
||||
# Allow sub2api user to restart the service without password
|
||||
# Support both /bin/systemctl (Debian/Ubuntu) and /usr/bin/systemctl (RHEL/CentOS)
|
||||
sub2api ALL=(ALL) NOPASSWD: /bin/systemctl restart sub2api
|
||||
sub2api ALL=(ALL) NOPASSWD: /bin/systemctl stop sub2api
|
||||
sub2api ALL=(ALL) NOPASSWD: /bin/systemctl start sub2api
|
||||
sub2api ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart sub2api
|
||||
sub2api ALL=(ALL) NOPASSWD: /usr/bin/systemctl stop sub2api
|
||||
sub2api ALL=(ALL) NOPASSWD: /usr/bin/systemctl start sub2api
|
||||
Reference in New Issue
Block a user