2026-09-23 09:40:59 +08:00
|
|
|
|
package frp
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"context"
|
|
|
|
|
|
"fmt"
|
|
|
|
|
|
"path/filepath"
|
|
|
|
|
|
"strings"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
func (s *Service) managerForServer(serverID int64) *Manager {
|
|
|
|
|
|
s.managersMu.Lock()
|
|
|
|
|
|
defer s.managersMu.Unlock()
|
|
|
|
|
|
if manager, ok := s.managers[serverID]; ok {
|
|
|
|
|
|
return manager
|
|
|
|
|
|
}
|
|
|
|
|
|
bin, err := s.manager.BinaryPath()
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
bin = s.cfg.FrpcBin
|
|
|
|
|
|
}
|
|
|
|
|
|
manager := NewManager(
|
|
|
|
|
|
bin,
|
|
|
|
|
|
s.serverConfigPath(serverID),
|
|
|
|
|
|
s.serverLogPath(serverID),
|
|
|
|
|
|
s.logger,
|
|
|
|
|
|
)
|
|
|
|
|
|
s.managers[serverID] = manager
|
|
|
|
|
|
return manager
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *Service) serverConfigPath(serverID int64) string {
|
|
|
|
|
|
return filepath.Join(s.cfg.FrpDir(), fmt.Sprintf("frpc-server-%d.toml", serverID))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *Service) serverLogPath(serverID int64) string {
|
|
|
|
|
|
return filepath.Join(s.cfg.FrpDir(), fmt.Sprintf("frpc-server-%d.log", serverID))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *Service) managerSnapshot() map[int64]*Manager {
|
|
|
|
|
|
s.managersMu.RLock()
|
|
|
|
|
|
defer s.managersMu.RUnlock()
|
|
|
|
|
|
result := make(map[int64]*Manager, len(s.managers))
|
|
|
|
|
|
for id, manager := range s.managers {
|
|
|
|
|
|
result[id] = manager
|
|
|
|
|
|
}
|
|
|
|
|
|
return result
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *Service) setManagerBinary(path string) {
|
|
|
|
|
|
s.manager.SetBinary(path)
|
|
|
|
|
|
for _, manager := range s.managerSnapshot() {
|
|
|
|
|
|
manager.SetBinary(path)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *Service) removeManager(serverID int64) {
|
|
|
|
|
|
s.managersMu.Lock()
|
|
|
|
|
|
delete(s.managers, serverID)
|
|
|
|
|
|
s.managersMu.Unlock()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func latestRuntimeStatus(statuses []RuntimeStatus) RuntimeStatus {
|
|
|
|
|
|
result := RuntimeStatus{Status: "stopped"}
|
|
|
|
|
|
for _, status := range statuses {
|
|
|
|
|
|
if status.Status == "running" {
|
|
|
|
|
|
result.Status = "running"
|
|
|
|
|
|
}
|
|
|
|
|
|
if status.Configured {
|
|
|
|
|
|
result.Configured = true
|
|
|
|
|
|
}
|
|
|
|
|
|
result.EnabledProxies += status.EnabledProxies
|
|
|
|
|
|
if result.PID == 0 && status.PID != 0 {
|
|
|
|
|
|
result.PID = status.PID
|
|
|
|
|
|
}
|
|
|
|
|
|
if status.LastStartedAt > result.LastStartedAt {
|
|
|
|
|
|
result.LastStartedAt = status.LastStartedAt
|
|
|
|
|
|
}
|
|
|
|
|
|
if status.LastReloadedAt > result.LastReloadedAt {
|
|
|
|
|
|
result.LastReloadedAt = status.LastReloadedAt
|
|
|
|
|
|
}
|
|
|
|
|
|
if result.LastError == "" && status.LastError != "" {
|
|
|
|
|
|
result.LastError = status.LastError
|
|
|
|
|
|
}
|
|
|
|
|
|
if status.Version != "" && result.Version == "" {
|
|
|
|
|
|
result.Version = status.Version
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if len(statuses) == 0 {
|
|
|
|
|
|
result.Status = "unknown"
|
|
|
|
|
|
}
|
|
|
|
|
|
return result
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (s *Service) waitForManagers(ctx context.Context, action func(*Manager) error) error {
|
|
|
|
|
|
var messages []string
|
|
|
|
|
|
for id, manager := range s.managerSnapshot() {
|
|
|
|
|
|
if err := action(manager); err != nil {
|
|
|
|
|
|
messages = append(messages, fmt.Sprintf("服务端 %d:%v", id, err))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if len(messages) > 0 {
|
|
|
|
|
|
return fmt.Errorf("%s", strings.Join(messages, ";"))
|
|
|
|
|
|
}
|
|
|
|
|
|
return nil
|
|
|
|
|
|
}
|
2026-10-07 19:26:02 +08:00
|
|
|
|
|
|
|
|
|
|
func sshSettingsChanged(existing, updated Server, secretUpdated bool) bool {
|
|
|
|
|
|
return existing.SSHHost != updated.SSHHost ||
|
|
|
|
|
|
existing.SSHPort != updated.SSHPort ||
|
|
|
|
|
|
existing.SSHUser != updated.SSHUser ||
|
|
|
|
|
|
existing.SSHAuth != updated.SSHAuth ||
|
|
|
|
|
|
secretUpdated
|
|
|
|
|
|
}
|