mirror of
https://github.com/daeuniverse/dae.git
synced 2025-02-22 20:49:59 +07:00
feat: support to suspend
This commit is contained in:
parent
ea568ebce5
commit
2b25e789db
@ -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)
|
|
||||||
}
|
|
||||||
|
@ -27,5 +27,6 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
rootCmd.AddCommand(exportCmd)
|
||||||
exportCmd.AddCommand(exportOutlineCmd)
|
exportCmd.AddCommand(exportOutlineCmd)
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
}
|
50
cmd/run.go
50
cmd/run.go
@ -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
47
cmd/suspend.go
Normal 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)
|
||||||
|
}
|
@ -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")
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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).
|
||||||
|
|
||||||
##
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
```
|
|
30
docs/getting-started/reload-and-suspend.md
Normal file
30
docs/getting-started/reload-and-suspend.md
Normal 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
|
||||||
|
```
|
||||||
|
|
Loading…
Reference in New Issue
Block a user