实现缓存功能

This commit is contained in:
Alex Yang
2025-11-30 20:20:59 +08:00
parent f623654151
commit c16e147931
33 changed files with 276 additions and 445090 deletions

91
main.go
View File

@@ -148,20 +148,9 @@ func createRequiredFiles(cfg *config.Config) error {
func main() {
// 命令行参数解析
var configFile string
var daemonMode bool
flag.StringVar(&configFile, "config", "config.json", "配置文件路径")
flag.BoolVar(&daemonMode, "daemon", false, "以守护进程模式运行")
flag.Parse()
// 如果是守护进程模式,创建守护进程
if daemonMode {
if err := daemonize(); err != nil {
log.Fatalf("创建守护进程失败: %v", err)
}
// 父进程退出
os.Exit(0)
}
// 检查配置文件是否存在,如果不存在则创建默认配置文件
if _, err := os.Stat(configFile); os.IsNotExist(err) {
log.Printf("配置文件 %s 不存在,正在创建默认配置文件...", configFile)
@@ -187,7 +176,7 @@ func main() {
log.Println("所需文件和文件夹创建成功")
// 初始化日志系统
if err := logger.InitLogger(cfg.Log.File, cfg.Log.Level, 0, 0, 0); err != nil {
if err := logger.InitLogger(cfg.Log.File, cfg.Log.Level, 0, 0, 0, false); err != nil {
log.Fatalf("初始化日志系统失败: %v", err)
}
defer logger.Close()
@@ -227,84 +216,10 @@ func main() {
<-sigCh
// 清理资源
log.Println("正在关闭服务...")
logger.Info("正在关闭服务...")
dnsServer.Stop()
httpServer.Stop()
shieldManager.StopAutoUpdate()
// 守护进程模式下不需要删除PID文件
log.Println("服务已关闭")
}
// daemonize 创建守护进程
func daemonize() error {
// 1. 第一次fork创建子进程父进程退出
pid, err := syscall.Fork()
if err != nil {
return fmt.Errorf("第一次fork失败: %w", err)
}
if pid > 0 {
// 父进程退出
os.Exit(0)
}
// 2. 设置文件权限掩码
syscall.Umask(0)
// 3. 创建新会话
_, err = syscall.Setsid()
if err != nil {
return fmt.Errorf("创建新会话失败: %w", err)
}
// 4. 第二次fork确保进程不是会话组长避免获取控制终端
pid, err = syscall.Fork()
if err != nil {
return fmt.Errorf("第二次fork失败: %w", err)
}
if pid > 0 {
// 父进程退出
os.Exit(0)
}
// 5. 切换工作目录到根目录
err = syscall.Chdir("/")
if err != nil {
return fmt.Errorf("切换工作目录失败: %w", err)
}
// 6. 关闭所有打开的文件描述符
for fd := 0; fd < 1024; fd++ {
syscall.Close(fd)
}
// 7. 重定向标准输入、输出、错误到/dev/null
nullFile, err := os.OpenFile("/dev/null", os.O_RDWR, 0)
if err != nil {
return fmt.Errorf("打开/dev/null失败: %w", err)
}
defer nullFile.Close()
// 重定向标准输入、输出、错误
syscall.Dup2(int(nullFile.Fd()), 0) // stdin
syscall.Dup2(int(nullFile.Fd()), 1) // stdout
syscall.Dup2(int(nullFile.Fd()), 2) // stderr
// 8. 处理SIGCHLD信号避免产生僵尸进程
syscall.Signal(syscall.SIGCHLD, syscall.SIG_IGN)
// 9. 写入PID文件
pid = syscall.Getpid()
pidFile, err := os.OpenFile("/var/run/dns-server.pid", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
return fmt.Errorf("打开PID文件失败: %w", err)
}
_, err = fmt.Fprintf(pidFile, "%d\n", pid)
if err != nil {
pidFile.Close()
return fmt.Errorf("写入PID文件失败: %w", err)
}
pidFile.Close()
return nil
logger.Info("服务已关闭")
}