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 {
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() {
rootCmd.AddCommand(exportCmd)
exportCmd.AddCommand(exportOutlineCmd)
}

View File

@ -6,26 +6,42 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
"github.com/v2rayA/dae/cmd/internal"
"os"
"strconv"
"strings"
"syscall"
)
var (
reloadCmd = &cobra.Command{
Use: "reload pid",
Use: "reload [pid]",
Run: func(cmd *cobra.Command, args []string) {
internal.AutoSu()
if len(args) == 0 {
cmd.Help()
_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)
}
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/config"
"github.com/v2rayA/dae/control"
"github.com/v2rayA/dae/pkg/config_parser"
"github.com/v2rayA/dae/pkg/logger"
"os"
"os/signal"
@ -92,6 +93,7 @@ func Run(log *logrus.Logger, conf *config.Config) (err error) {
sigs <- nil
}()
reloading := false
isSuspend := false
loop:
for sig := range sigs {
switch sig {
@ -114,6 +116,9 @@ loop:
// Listening error.
break loop
}
case syscall.SIGHUP:
isSuspend = true
fallthrough
case syscall.SIGUSR1:
// Reload signal.
log.Warnln("[Reload] Received reload signal; prepare to reload")
@ -121,7 +126,20 @@ loop:
// Load new config.
log.Warnln("[Reload] Load new config")
newConf, includes, err := readConfig(cfgFile)
var newConf *config.Config
if isSuspend {
isSuspend = false
newConf, err = emptyConfig()
if err != nil {
log.WithFields(logrus.Fields{
"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,
@ -130,6 +148,7 @@ loop:
continue
}
log.Infof("Include config files: [%v]", strings.Join(includes, ", "))
}
// New logger.
log = logger.NewLogger(newConf.Global.LogLevel, disableTimestamp)
logrus.SetLevel(log.Level)
@ -244,3 +263,18 @@ func readConfig(cfgFile string) (conf *config.Config, includes []string, err err
}
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() {
rootCmd.AddCommand(validateCmd)
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)
if err != nil {
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.
bReq := pool.Get(2 + len(data))
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).
##
```
```

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
```