Files
dns-server/main.go

126 lines
3.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package main
import (
"flag"
"fmt"
"log"
"os"
"os/signal"
"syscall"
"dns-server/config"
"dns-server/dns"
"dns-server/http"
"dns-server/logger"
"dns-server/shield"
)
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)
}
// 初始化配置
var cfg *config.Config
var err error
cfg, err = config.LoadConfig(configFile)
if err != nil {
log.Fatalf("加载配置失败: %v", err)
}
// 初始化日志系统
if err := logger.InitLogger(cfg.Log.File, cfg.Log.Level, 0, 0, 0); err != nil {
log.Fatalf("初始化日志系统失败: %v", err)
}
defer logger.Close()
// 初始化屏蔽管理系统
shieldManager := shield.NewShieldManager(&cfg.Shield)
if err := shieldManager.LoadRules(); err != nil {
logger.Error("加载屏蔽规则失败", "error", err)
}
// 启动DNS服务器
dnsServer := dns.NewServer(&cfg.DNS, &cfg.Shield, shieldManager)
go func() {
if err := dnsServer.Start(); err != nil {
logger.Error("DNS服务器启动失败", "error", err)
os.Exit(1)
}
}()
// 启动HTTP控制台服务器
httpServer := http.NewServer(cfg, dnsServer, shieldManager)
go func() {
if err := httpServer.Start(); err != nil {
logger.Error("HTTP控制台服务器启动失败", "error", err)
}
}()
// 启动定时更新任务
go shieldManager.StartAutoUpdate()
logger.Info(fmt.Sprintf("DNS服务器已启动监听端口: %d", cfg.DNS.Port))
logger.Info(fmt.Sprintf("HTTP控制台已启动监听端口: %d", cfg.HTTP.Port))
// 监听信号
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
<-sigCh
// 清理资源
log.Println("正在关闭服务...")
dnsServer.Stop()
httpServer.Stop()
shieldManager.StopAutoUpdate()
// 守护进程模式下不需要删除PID文件
log.Println("服务已关闭")
}
// daemonize 创建守护进程
func daemonize() error {
// 使用更简单的方式创建守护进程:直接在当前进程中进行守护化处理
// 1. 重定向标准输入、输出、错误
nullFile, err := os.OpenFile("/dev/null", os.O_RDWR, 0)
if err != nil {
return fmt.Errorf("打开/dev/null失败: %w", err)
}
defer nullFile.Close()
// 重定向文件描述符
err = syscall.Dup2(int(nullFile.Fd()), int(os.Stdin.Fd()))
if err != nil {
return fmt.Errorf("重定向stdin失败: %w", err)
}
err = syscall.Dup2(int(nullFile.Fd()), int(os.Stdout.Fd()))
if err != nil {
return fmt.Errorf("重定向stdout失败: %w", err)
}
err = syscall.Dup2(int(nullFile.Fd()), int(os.Stderr.Fd()))
if err != nil {
return fmt.Errorf("重定向stderr失败: %w", err)
}
// 2. 创建新的会话和进程组
_, err = syscall.Setsid()
if err != nil {
return fmt.Errorf("创建新会话失败: %w", err)
}
fmt.Println("守护进程已启动")
return nil
}