// Copyright 2016 fatedier, fatedier@gmail.com // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "os" "os/signal" "path/filepath" "syscall" "time" ini "github.com/vaughan0/go-ini" "github.com/fatedier/frp/client" "github.com/fatedier/frp/models/config" "github.com/fatedier/frp/utils/log" "github.com/kardianos/service" ) var logger service.Logger 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() { var err error fileDir := filepath.Dir(os.Args[0]) confFile := filepath.Join(fileDir, "frpc.ini") logger.Infof("get config file path:%s", confFile) conf, err := ini.LoadFile(confFile) if err != nil { logger.Error(err) os.Exit(1) } config.ClientCommonCfg, err = config.LoadClientCommonConf(conf) if err != nil { logger.Error(err) os.Exit(1) } config.ClientCommonCfg.ConfigFile = confFile pxyCfgs, visitorCfgs, err := config.LoadProxyConfFromFile(config.ClientCommonCfg.User, conf, config.ClientCommonCfg.Start) if err != nil { logger.Error(err) os.Exit(1) } log.InitLog(config.ClientCommonCfg.LogWay, config.ClientCommonCfg.LogFile, config.ClientCommonCfg.LogLevel, config.ClientCommonCfg.LogMaxDays) svr := client.NewService(pxyCfgs, visitorCfgs) // Capture the exit signal if we use kcp. if config.ClientCommonCfg.Protocol == "kcp" { go HandleSignal(svr) } err = svr.Run() if err != nil { logger.Error(err) os.Exit(1) } } func HandleSignal(svr *client.Service) { ch := make(chan os.Signal) signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) <-ch svr.Close() time.Sleep(250 * time.Millisecond) os.Exit(0) } func (p *program) Stop(s service.Service) error { // Stop should not block. Return with a few seconds. return nil } func main() { svcConfig := &service.Config{ Name: "frpc service", DisplayName: "frpc service", Description: "config file frpc.ini", } prg := &program{} s, err := service.New(prg, svcConfig) if err != nil { log.Error(err.Error()) } logger, err = s.Logger(nil) if err != nil { log.Error(err.Error()) } if len(os.Args) == 2 { //如果有命令则执行 err = service.Control(s, os.Args[1]) if err != nil { logger.Error(err) } } else { //否则说明是方法启动了 err = s.Run() if err != nil { logger.Error(err) } } if err != nil { logger.Error(err) } }