feat: support to suspend

This commit is contained in:
mzz2017 2023-03-14 00:34:38 +08:00
parent ea568ebce5
commit 2b25e789db
9 changed files with 144 additions and 27 deletions

View File

@ -21,10 +21,3 @@ var (
func Execute() error { func Execute() error {
return rootCmd.Execute() return rootCmd.Execute()
} }
func init() {
rootCmd.AddCommand(runCmd)
rootCmd.AddCommand(validateCmd)
rootCmd.AddCommand(exportCmd)
rootCmd.AddCommand(reloadCmd)
}

View File

@ -27,5 +27,6 @@ var (
) )
func init() { func init() {
rootCmd.AddCommand(exportCmd)
exportCmd.AddCommand(exportOutlineCmd) exportCmd.AddCommand(exportOutlineCmd)
} }

View File

@ -6,26 +6,42 @@
package cmd package cmd
import ( import (
"fmt"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/v2rayA/dae/cmd/internal"
"os" "os"
"strconv" "strconv"
"strings"
"syscall" "syscall"
) )
var ( var (
reloadCmd = &cobra.Command{ reloadCmd = &cobra.Command{
Use: "reload pid", Use: "reload [pid]",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
internal.AutoSu()
if len(args) == 0 { if len(args) == 0 {
cmd.Help() _pid, err := os.ReadFile(PidFilePath)
os.Exit(1) if err != nil {
fmt.Println("Failed to read pid file:", err)
os.Exit(1)
}
args = []string{strings.TrimSpace(string(_pid))}
} }
pid, err := strconv.Atoi(args[0]) pid, err := strconv.Atoi(args[0])
if err != nil { if err != nil {
cmd.Help() cmd.Help()
os.Exit(1) os.Exit(1)
} }
syscall.Kill(pid, syscall.SIGUSR1) if err = syscall.Kill(pid, syscall.SIGUSR1); err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println("OK")
}, },
} }
) )
func init() {
rootCmd.AddCommand(reloadCmd)
}

View File

@ -10,6 +10,7 @@ import (
"github.com/v2rayA/dae/common/subscription" "github.com/v2rayA/dae/common/subscription"
"github.com/v2rayA/dae/config" "github.com/v2rayA/dae/config"
"github.com/v2rayA/dae/control" "github.com/v2rayA/dae/control"
"github.com/v2rayA/dae/pkg/config_parser"
"github.com/v2rayA/dae/pkg/logger" "github.com/v2rayA/dae/pkg/logger"
"os" "os"
"os/signal" "os/signal"
@ -92,6 +93,7 @@ func Run(log *logrus.Logger, conf *config.Config) (err error) {
sigs <- nil sigs <- nil
}() }()
reloading := false reloading := false
isSuspend := false
loop: loop:
for sig := range sigs { for sig := range sigs {
switch sig { switch sig {
@ -114,6 +116,9 @@ loop:
// Listening error. // Listening error.
break loop break loop
} }
case syscall.SIGHUP:
isSuspend = true
fallthrough
case syscall.SIGUSR1: case syscall.SIGUSR1:
// Reload signal. // Reload signal.
log.Warnln("[Reload] Received reload signal; prepare to reload") log.Warnln("[Reload] Received reload signal; prepare to reload")
@ -121,15 +126,29 @@ loop:
// Load new config. // Load new config.
log.Warnln("[Reload] Load new config") log.Warnln("[Reload] Load new config")
newConf, includes, err := readConfig(cfgFile) var newConf *config.Config
if err != nil { if isSuspend {
log.WithFields(logrus.Fields{ isSuspend = false
"err": err, newConf, err = emptyConfig()
}).Errorln("[Reload] Failed to reload") if err != nil {
sdnotify.Ready() log.WithFields(logrus.Fields{
continue "err": err,
}).Errorln("[Reload] Failed to reload")
sdnotify.Ready()
continue
}
} else {
var includes []string
newConf, includes, err = readConfig(cfgFile)
if err != nil {
log.WithFields(logrus.Fields{
"err": err,
}).Errorln("[Reload] Failed to reload")
sdnotify.Ready()
continue
}
log.Infof("Include config files: [%v]", strings.Join(includes, ", "))
} }
log.Infof("Include config files: [%v]", strings.Join(includes, ", "))
// New logger. // New logger.
log = logger.NewLogger(newConf.Global.LogLevel, disableTimestamp) log = logger.NewLogger(newConf.Global.LogLevel, disableTimestamp)
logrus.SetLevel(log.Level) logrus.SetLevel(log.Level)
@ -244,3 +263,18 @@ func readConfig(cfgFile string) (conf *config.Config, includes []string, err err
} }
return conf, includes, nil return conf, includes, nil
} }
func emptyConfig() (conf *config.Config, err error) {
sections, err := config_parser.Parse(`global{} routing{}`)
if err != nil {
return nil, err
}
if conf, err = config.New(sections); err != nil {
return nil, err
}
return conf, nil
}
func init() {
rootCmd.AddCommand(runCmd)
}

47
cmd/suspend.go Normal file
View File

@ -0,0 +1,47 @@
/*
* SPDX-License-Identifier: AGPL-3.0-only
* Copyright (c) 2023, v2rayA Organization <team@v2raya.org>
*/
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"github.com/v2rayA/dae/cmd/internal"
"os"
"strconv"
"strings"
"syscall"
)
var (
suspendCmd = &cobra.Command{
Use: "suspend [pid]",
Run: func(cmd *cobra.Command, args []string) {
internal.AutoSu()
if len(args) == 0 {
_pid, err := os.ReadFile(PidFilePath)
if err != nil {
fmt.Println("Failed to read pid file:", err)
os.Exit(1)
}
args = []string{strings.TrimSpace(string(_pid))}
}
pid, err := strconv.Atoi(args[0])
if err != nil {
cmd.Help()
os.Exit(1)
}
if err = syscall.Kill(pid, syscall.SIGHUP); err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println("OK")
},
}
)
func init() {
rootCmd.AddCommand(suspendCmd)
}

View File

@ -31,5 +31,7 @@ var (
) )
func init() { func init() {
rootCmd.AddCommand(validateCmd)
validateCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file") validateCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file")
} }

View File

@ -399,7 +399,7 @@ func (c *DnsController) dialSend(req *udpRequest, data []byte, upstream *dns.Ups
} }
}() }()
_ = conn.SetDeadline(time.Now().Add(DnsNatTimeout)) _ = conn.SetDeadline(time.Now().Add(5 * time.Second))
_, err = conn.Write(data) _, err = conn.Write(data)
if err != nil { if err != nil {
if c.log.IsLevelEnabled(logrus.DebugLevel) { if c.log.IsLevelEnabled(logrus.DebugLevel) {
@ -446,7 +446,7 @@ func (c *DnsController) dialSend(req *udpRequest, data []byte, upstream *dns.Ups
} }
}() }()
_ = conn.SetDeadline(time.Now().Add(DnsNatTimeout)) _ = conn.SetDeadline(time.Now().Add(5 * time.Second))
// We should write two byte length in the front of TCP DNS request. // We should write two byte length in the front of TCP DNS request.
bReq := pool.Get(2 + len(data)) bReq := pool.Get(2 + len(data))
defer pool.Put(bReq) defer pool.Put(bReq)

View File

@ -83,9 +83,3 @@ You should configure dae as follows:
4. If you bind to LAN, make sure your DHCP server will distribute dae as the DNS server (DNS request should be forwarded by dae for domain based traffic split). 4. If you bind to LAN, make sure your DHCP server will distribute dae as the DNS server (DNS request should be forwarded by dae for domain based traffic split).
##
```
```

View File

@ -0,0 +1,30 @@
# Reload and Suspend
dae supports configuration reloading and program suspending, which can help you save a lot of time when modifying the configuration or temporarily suspend dae.
**Reload**
Generally, dae won't interrupt connections when reloading configuration. And it is very fast compared to restart.
Usage:
```shell
dae reload
```
**Suspend**
It will be useful if you want to suspend dae temporarily and recover it later.
Usage:
```shell
dae suspend
```
If you want to recover, use reload:
```shell
dae reload
```