| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 | package mainimport (	"backup-x/client"	"backup-x/util"	"backup-x/web"	"embed"	"flag"	"net"	"os"	"log"	"net/http"	"time"	"github.com/kardianos/service")// 监听地址var listen = flag.String("l", ":9977", "监听地址")// 服务管理var serviceType = flag.String("s", "", "服务管理, 支持install, uninstall")// 默认备份路径当前运行目录var backupDirDefault, _ = os.Getwd()// 配置文件路径var backupDir = flag.String("d", backupDirDefault, "自定义备份目录地址")//go:embed staticvar staticEmbededFiles embed.FS//go:embed favicon.icovar faviconEmbededFile embed.FS// versionvar version = "DEV"func main() {	flag.Parse()	if _, err := net.ResolveTCPAddr("tcp", *listen); err != nil {		log.Fatalf("解析监听地址异常,%s", err)	}	os.Setenv(web.VersionEnv, version)	switch *serviceType {	case "install":		installService()	case "uninstall":		uninstallService()	default:		if util.IsRunInDocker() {			run()		} else {			s := getService()			status, _ := s.Status()			if status != service.StatusUnknown {				// 以服务方式运行				s.Run()			} else {				// 非服务方式运行				switch s.Platform() {				case "windows-service":					log.Println("可使用 .\\backup-x.exe -s install 安装服务运行")				default:					log.Println("可使用 ./backup-x -s install 安装服务运行")				}				run()			}		}	}}func staticFsFunc(writer http.ResponseWriter, request *http.Request) {	http.FileServer(http.FS(staticEmbededFiles)).ServeHTTP(writer, request)}func faviconFsFunc(writer http.ResponseWriter, request *http.Request) {	http.FileServer(http.FS(faviconEmbededFile)).ServeHTTP(writer, request)}func run() {	// 启动静态文件服务	http.HandleFunc("/static/", web.BasicAuth(staticFsFunc))	http.HandleFunc("/favicon.ico", web.BasicAuth(faviconFsFunc))	http.HandleFunc("/", web.BasicAuth(web.WritingConfig))	http.HandleFunc("/save", web.BasicAuth(web.Save))	http.HandleFunc("/logs", web.BasicAuth(web.Logs))	http.HandleFunc("/clearLog", web.BasicAuth(web.ClearLog))	http.HandleFunc("/webhookTest", web.BasicAuth(web.WebhookTest))	// 改变工作目录	os.Chdir(*backupDir)	// 运行	go client.DeleteOldBackup()	go client.RunLoop()	err := http.ListenAndServe(*listen, nil)	if err != nil {		log.Println("启动端口发生异常, 请检查端口是否被占用", err)		time.Sleep(time.Minute)	}}type program struct{}func (p *program) Start(s service.Service) error {	// Start should not block. Do the actual work async.	go p.run()	return nil}func (p *program) run() {	// 服务运行,延时20秒运行,等待网络	time.Sleep(20 * time.Second)	run()}func (p *program) Stop(s service.Service) error {	// Stop should not block. Return with a few seconds.	return nil}func getService() service.Service {	options := make(service.KeyValue)	var depends []string	// 确保服务等待网络就绪后再启动	switch service.ChosenSystem().String() {	case "windows-service":		// 将 Windows 服务的启动类型设为自动(延迟启动)		options["DelayedAutoStart"] = true	default:		// 向 Systemd 添加网络依赖		depends = append(depends, "Requires=network.target",			"After=network-online.target")	}	svcConfig := &service.Config{		Name:         "backup-x",		DisplayName:  "backup-x",		Description:  "带Web界面的数据库/文件备份增强工具",		Arguments:    []string{"-l", *listen, "-d", *backupDir},		Dependencies: depends,		Option:       options,	}	prg := &program{}	s, err := service.New(prg, svcConfig)	if err != nil {		log.Fatalln(err)	}	return s}// 卸载服务func uninstallService() {	s := getService()	status, _ := s.Status()	// 处理卸载	if status != service.StatusUnknown {		s.Stop()		if err := s.Uninstall(); err == nil {			log.Println("backup-x 服务卸载成功!")		} else {			log.Printf("backup-x 服务卸载失败, ERR: %s\n", err)		}	} else {		log.Printf("backup-x 服务未安装")	}}// 安装服务func installService() {	s := getService()	status, err := s.Status()	if err != nil && status == service.StatusUnknown {		// 服务未知,创建服务		if err = s.Install(); err == nil {			s.Start()			log.Println("安装 backup-x 服务成功! 程序会一直运行, 包括重启后。")			return		}		log.Printf("安装 backup-x 服务失败, ERR: %s\n", err)		switch s.Platform() {		case "windows-service":			log.Println("请确保使用如下命令: .\\backup-x.exe -s install")		default:			log.Println("请确保使用如下命令: ./backup-x -s install")		}	}	if status != service.StatusUnknown {		log.Println("backup-x 服务已安装, 无需再次安装")	}}
 |