mirror of
https://github.com/wyx2685/V2bX.git
synced 2026-02-04 12:40:11 +00:00
add manage command
This commit is contained in:
109
cmd/action_linux.go
Normal file
109
cmd/action_linux.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
startCommand = cobra.Command{
|
||||
Use: "start",
|
||||
Short: "Start V2bX service",
|
||||
Run: startHandle,
|
||||
}
|
||||
stopCommand = cobra.Command{
|
||||
Use: "stop",
|
||||
Short: "Stop V2bX service",
|
||||
Run: stopHandle,
|
||||
}
|
||||
restartCommand = cobra.Command{
|
||||
Use: "restart",
|
||||
Short: "Restart V2bX service",
|
||||
Run: restartHandle,
|
||||
}
|
||||
logCommand = cobra.Command{
|
||||
Use: "log",
|
||||
Short: "Output V2bX log",
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
execCommandStd("journalctl", "-u", "V2bX.service", "-e", "--no-pager", "-f")
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
command.AddCommand(&startCommand)
|
||||
command.AddCommand(&stopCommand)
|
||||
command.AddCommand(&restartCommand)
|
||||
command.AddCommand(&logCommand)
|
||||
}
|
||||
|
||||
func startHandle(_ *cobra.Command, _ []string) {
|
||||
r, err := checkRunning()
|
||||
if err != nil {
|
||||
fmt.Println(Err("check status error: ", err))
|
||||
fmt.Println(Err("V2bX启动失败"))
|
||||
return
|
||||
}
|
||||
if r {
|
||||
fmt.Println(Ok("V2bX已运行,无需再次启动,如需重启请选择重启"))
|
||||
}
|
||||
_, err = execCommand("systemctl start V2bX.service")
|
||||
if err != nil {
|
||||
fmt.Println(Err("exec start cmd error: ", err))
|
||||
fmt.Println(Err("V2bX启动失败"))
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Second * 3)
|
||||
r, err = checkRunning()
|
||||
if err != nil {
|
||||
fmt.Println(Err("check status error: ", err))
|
||||
fmt.Println(Err("V2bX启动失败"))
|
||||
}
|
||||
if !r {
|
||||
fmt.Println(Err("V2bX可能启动失败,请稍后使用 V2bX log 查看日志信息"))
|
||||
return
|
||||
}
|
||||
fmt.Println(Ok("V2bX 启动成功,请使用 V2bX log 查看运行日志"))
|
||||
}
|
||||
|
||||
func stopHandle(_ *cobra.Command, _ []string) {
|
||||
_, err := execCommand("systemctl stop V2bX.service")
|
||||
if err != nil {
|
||||
fmt.Println(Err("exec stop cmd error: ", err))
|
||||
fmt.Println(Err("V2bX停止失败"))
|
||||
return
|
||||
}
|
||||
time.Sleep(2 * time.Second)
|
||||
r, err := checkRunning()
|
||||
if err != nil {
|
||||
fmt.Println(Err("check status error:", err))
|
||||
fmt.Println(Err("V2bX停止失败"))
|
||||
return
|
||||
}
|
||||
if r {
|
||||
fmt.Println(Err("V2bX停止失败,可能是因为停止时间超过了两秒,请稍后查看日志信息"))
|
||||
return
|
||||
}
|
||||
fmt.Println(Ok("V2bX 停止成功"))
|
||||
}
|
||||
|
||||
func restartHandle(_ *cobra.Command, _ []string) {
|
||||
_, err := execCommand("systemctl restart V2bX.service")
|
||||
if err != nil {
|
||||
fmt.Println(Err("exec restart cmd error: ", err))
|
||||
fmt.Println(Err("V2bX重启失败"))
|
||||
return
|
||||
}
|
||||
r, err := checkRunning()
|
||||
if err != nil {
|
||||
fmt.Println(Err("check status error: ", err))
|
||||
fmt.Println(Err("V2bX重启失败"))
|
||||
return
|
||||
}
|
||||
if !r {
|
||||
fmt.Println(Err("V2bX可能启动失败,请稍后使用 V2bX log 查看日志信息"))
|
||||
return
|
||||
}
|
||||
fmt.Println(Ok("V2bX重启成功"))
|
||||
}
|
||||
34
cmd/cmd.go
Normal file
34
cmd/cmd.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"log"
|
||||
)
|
||||
|
||||
var (
|
||||
version = "TempVersion" //use ldflags replace
|
||||
codename = "V2bX"
|
||||
intro = "A V2board backend based on Xray-core"
|
||||
)
|
||||
|
||||
func showVersion() {
|
||||
fmt.Printf("%s %s (%s) \n", codename, version, intro)
|
||||
// Warning
|
||||
fmt.Println(Warn("This version need V2board version >= 1.7.0."))
|
||||
fmt.Println(Warn("This version changed config file. Please check config file before running."))
|
||||
}
|
||||
|
||||
var command = &cobra.Command{
|
||||
Use: "V2bX",
|
||||
PreRun: func(_ *cobra.Command, _ []string) {
|
||||
showVersion()
|
||||
},
|
||||
}
|
||||
|
||||
func Run() {
|
||||
err := command.Execute()
|
||||
if err != nil {
|
||||
log.Println("execute failed, error:", err)
|
||||
}
|
||||
}
|
||||
33
cmd/common.go
Normal file
33
cmd/common.go
Normal file
@@ -0,0 +1,33 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
red = "\033[0;31m"
|
||||
green = "\033[0;32m"
|
||||
yellow = "\033[0;33m"
|
||||
plain = "\033[0m"
|
||||
)
|
||||
|
||||
func checkRunning() (bool, error) {
|
||||
o, err := execCommand("systemctl status V2bX | grep Active")
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return strings.Contains(o, "running"), nil
|
||||
}
|
||||
|
||||
func Err(msg ...any) string {
|
||||
return red + fmt.Sprint(msg...) + plain
|
||||
}
|
||||
|
||||
func Ok(msg ...any) string {
|
||||
return green + fmt.Sprint(msg...) + plain
|
||||
}
|
||||
|
||||
func Warn(msg ...any) string {
|
||||
return yellow + fmt.Sprint(msg...) + plain
|
||||
}
|
||||
11
cmd/common_test.go
Normal file
11
cmd/common_test.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package cmd
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestExecCommand(t *testing.T) {
|
||||
t.Log(execCommand("echo test"))
|
||||
}
|
||||
|
||||
func Test_printFailed(t *testing.T) {
|
||||
t.Log(Err("test"))
|
||||
}
|
||||
25
cmd/exec.go
Normal file
25
cmd/exec.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func execCommand(cmd string) (string, error) {
|
||||
e := exec.Command("bash", "-c", cmd)
|
||||
out, err := e.CombinedOutput()
|
||||
if errors.Unwrap(err) == exec.ErrNotFound {
|
||||
e = exec.Command("sh", "-c", cmd)
|
||||
out, err = e.CombinedOutput()
|
||||
}
|
||||
return string(out), err
|
||||
}
|
||||
|
||||
func execCommandStd(name string, args ...string) {
|
||||
e := exec.Command(name, args...)
|
||||
e.Stdout = os.Stdout
|
||||
e.Stdin = os.Stdin
|
||||
e.Stderr = os.Stderr
|
||||
_ = e.Run()
|
||||
}
|
||||
59
cmd/install_linux.go
Normal file
59
cmd/install_linux.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/cobra"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var targetVersion string
|
||||
|
||||
var (
|
||||
updateCommand = cobra.Command{
|
||||
Use: "update",
|
||||
Short: "Update V2bX version",
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
c := execCommandStd("bash",
|
||||
"<(curl -Ls https://raw.githubusercontents.com/Yuzuki616/V2bX-script/master/install.sh)",
|
||||
targetVersion)
|
||||
},
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
uninstallCommand = cobra.Command{
|
||||
Use: "uninstall",
|
||||
Short: "Uninstall V2bX",
|
||||
Run: uninstallHandle,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
updateCommand.PersistentFlags().StringVar(&targetVersion, "version", "", "update target version")
|
||||
command.AddCommand(&updateCommand)
|
||||
command.AddCommand(&uninstallCommand)
|
||||
}
|
||||
|
||||
func uninstallHandle(_ *cobra.Command, _ []string) {
|
||||
var yes string
|
||||
fmt.Println(Warn("确定要卸载 V2bX 吗?(Y/n)"))
|
||||
fmt.Scan(&yes)
|
||||
if strings.ToLower(yes) != "y" {
|
||||
fmt.Println("已取消卸载")
|
||||
}
|
||||
_, err := execCommand("systemctl stop V2bX&&systemctl disable V2bX")
|
||||
if err != nil {
|
||||
fmt.Println(Err("exec cmd error: ", err))
|
||||
fmt.Println(Err("卸载失败"))
|
||||
return
|
||||
}
|
||||
_ = os.RemoveAll("/etc/systemd/system/V2bX.service")
|
||||
_ = os.RemoveAll("/etc/V2bX/")
|
||||
_ = os.RemoveAll("/usr/local/V2bX/")
|
||||
_, err = execCommand("systemctl daemon-reload&&systemctl reset-failed")
|
||||
if err != nil {
|
||||
fmt.Println(Err("exec cmd error: ", err))
|
||||
fmt.Println(Err("卸载失败"))
|
||||
return
|
||||
}
|
||||
fmt.Println(Ok("卸载成功"))
|
||||
}
|
||||
83
cmd/server.go
Normal file
83
cmd/server.go
Normal file
@@ -0,0 +1,83 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/Yuzuki616/V2bX/conf"
|
||||
"github.com/Yuzuki616/V2bX/core"
|
||||
"github.com/Yuzuki616/V2bX/limiter"
|
||||
"github.com/Yuzuki616/V2bX/node"
|
||||
"github.com/spf13/cobra"
|
||||
"log"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
var (
|
||||
config string
|
||||
watch bool
|
||||
)
|
||||
|
||||
var serverCommand = cobra.Command{
|
||||
Use: "server",
|
||||
Short: "Run V2bX server",
|
||||
Run: serverHandle,
|
||||
Args: cobra.NoArgs,
|
||||
}
|
||||
|
||||
func init() {
|
||||
serverCommand.PersistentFlags().
|
||||
StringVarP(&config, "config", "c",
|
||||
"/etc/V2bX/config.yml", "config file path")
|
||||
serverCommand.PersistentFlags().
|
||||
BoolVarP(&watch, "watch", "w",
|
||||
true, "watch file path change")
|
||||
command.AddCommand(&serverCommand)
|
||||
}
|
||||
|
||||
func serverHandle(_ *cobra.Command, _ []string) {
|
||||
c := conf.New()
|
||||
err := c.LoadFromPath(config)
|
||||
if err != nil {
|
||||
log.Fatalf("can't unmarshal config file: %s \n", err)
|
||||
}
|
||||
limiter.Init()
|
||||
log.Println("Start V2bX...")
|
||||
x := core.New(c)
|
||||
err = x.Start()
|
||||
if err != nil {
|
||||
log.Fatalf("Start xray-core error: %s", err)
|
||||
}
|
||||
defer x.Close()
|
||||
nodes := node.New()
|
||||
err = nodes.Start(c.NodesConfig, x)
|
||||
if err != nil {
|
||||
log.Fatalf("Run nodes error: %s", err)
|
||||
return
|
||||
}
|
||||
if watch {
|
||||
err = c.Watch(config, func() {
|
||||
nodes.Close()
|
||||
err = x.Restart(c)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to restart xray-core: %s", err)
|
||||
}
|
||||
err = nodes.Start(c.NodesConfig, x)
|
||||
if err != nil {
|
||||
log.Fatalf("run nodes error: %s", err)
|
||||
}
|
||||
runtime.GC()
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatalf("watch config file error: %s", err)
|
||||
}
|
||||
}
|
||||
// clear memory
|
||||
runtime.GC()
|
||||
// wait exit signal
|
||||
{
|
||||
osSignals := make(chan os.Signal, 1)
|
||||
signal.Notify(osSignals, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM)
|
||||
<-osSignals
|
||||
}
|
||||
}
|
||||
7
cmd/server_test.go
Normal file
7
cmd/server_test.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package cmd
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestRun(t *testing.T) {
|
||||
Run()
|
||||
}
|
||||
38
cmd/synctime.go
Normal file
38
cmd/synctime.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/beevik/ntp"
|
||||
"github.com/sagernet/sing-box/common/settings"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var ntpServer string
|
||||
|
||||
var commandSyncTime = &cobra.Command{
|
||||
Use: "synctime",
|
||||
Short: "Sync time from ntp server",
|
||||
Args: cobra.NoArgs,
|
||||
Run: synctimeHandle,
|
||||
}
|
||||
|
||||
func init() {
|
||||
commandSyncTime.Flags().StringVar(&ntpServer, "server", "time.apple.com", "ntp server")
|
||||
command.AddCommand(commandSyncTime)
|
||||
}
|
||||
|
||||
func synctimeHandle(_ *cobra.Command, _ []string) {
|
||||
t, err := ntp.Time(ntpServer)
|
||||
if err != nil {
|
||||
fmt.Println(Err("get time from server error: ", err))
|
||||
fmt.Println(Err("同步时间失败"))
|
||||
return
|
||||
}
|
||||
err = settings.SetSystemTime(t)
|
||||
if err != nil {
|
||||
fmt.Println(Err("set system time error: ", err))
|
||||
fmt.Println(Err("同步时间失败"))
|
||||
return
|
||||
}
|
||||
fmt.Println(Ok("同步时间成功"))
|
||||
}
|
||||
Reference in New Issue
Block a user