mirror of
https://github.com/TeaOSLab/EdgeNode.git
synced 2025-11-03 23:20:25 +08:00
227 lines
4.1 KiB
Go
227 lines
4.1 KiB
Go
package apps
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/iwind/TeaGo/Tea"
|
|
"github.com/iwind/TeaGo/logs"
|
|
"os"
|
|
"os/exec"
|
|
"runtime"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
// App命令帮助
|
|
type AppCmd struct {
|
|
product string
|
|
version string
|
|
usage string
|
|
options []*CommandHelpOption
|
|
appendStrings []string
|
|
|
|
directives []*Directive
|
|
}
|
|
|
|
func NewAppCmd() *AppCmd {
|
|
return &AppCmd{}
|
|
}
|
|
|
|
type CommandHelpOption struct {
|
|
Code string
|
|
Description string
|
|
}
|
|
|
|
// 产品
|
|
func (this *AppCmd) Product(product string) *AppCmd {
|
|
this.product = product
|
|
return this
|
|
}
|
|
|
|
// 版本
|
|
func (this *AppCmd) Version(version string) *AppCmd {
|
|
this.version = version
|
|
return this
|
|
}
|
|
|
|
// 使用方法
|
|
func (this *AppCmd) Usage(usage string) *AppCmd {
|
|
this.usage = usage
|
|
return this
|
|
}
|
|
|
|
// 选项
|
|
func (this *AppCmd) Option(code string, description string) *AppCmd {
|
|
this.options = append(this.options, &CommandHelpOption{
|
|
Code: code,
|
|
Description: description,
|
|
})
|
|
return this
|
|
}
|
|
|
|
// 附加内容
|
|
func (this *AppCmd) Append(appendString string) *AppCmd {
|
|
this.appendStrings = append(this.appendStrings, appendString)
|
|
return this
|
|
}
|
|
|
|
// 打印
|
|
func (this *AppCmd) Print() {
|
|
fmt.Println(this.product + " v" + this.version)
|
|
|
|
usage := this.usage
|
|
fmt.Println("Usage:", "\n "+usage)
|
|
|
|
if len(this.options) > 0 {
|
|
fmt.Println("")
|
|
fmt.Println("Options:")
|
|
|
|
spaces := 20
|
|
max := 40
|
|
for _, option := range this.options {
|
|
l := len(option.Code)
|
|
if l < max && l > spaces {
|
|
spaces = l + 4
|
|
}
|
|
}
|
|
|
|
for _, option := range this.options {
|
|
if len(option.Code) > max {
|
|
fmt.Println("")
|
|
fmt.Println(" " + option.Code)
|
|
option.Code = ""
|
|
}
|
|
|
|
fmt.Printf(" %-"+strconv.Itoa(spaces)+"s%s\n", option.Code, ": "+option.Description)
|
|
}
|
|
}
|
|
|
|
if len(this.appendStrings) > 0 {
|
|
fmt.Println("")
|
|
for _, s := range this.appendStrings {
|
|
fmt.Println(s)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 添加指令
|
|
func (this *AppCmd) On(arg string, callback func()) {
|
|
this.directives = append(this.directives, &Directive{
|
|
Arg: arg,
|
|
Callback: callback,
|
|
})
|
|
}
|
|
|
|
// 运行
|
|
func (this *AppCmd) Run(main func()) {
|
|
// 获取参数
|
|
args := os.Args[1:]
|
|
if len(args) > 0 {
|
|
switch args[0] {
|
|
case "-v", "version", "-version", "--version":
|
|
this.runVersion()
|
|
return
|
|
case "?", "help", "-help", "h", "-h":
|
|
this.runHelp()
|
|
return
|
|
case "start":
|
|
this.runStart()
|
|
return
|
|
case "stop":
|
|
this.runStop()
|
|
return
|
|
case "restart":
|
|
this.runRestart()
|
|
return
|
|
case "status":
|
|
this.runStatus()
|
|
return
|
|
}
|
|
|
|
// 查找指令
|
|
for _, directive := range this.directives {
|
|
if directive.Arg == args[0] {
|
|
directive.Callback()
|
|
return
|
|
}
|
|
}
|
|
|
|
fmt.Println("unknown command '" + args[0] + "'")
|
|
|
|
return
|
|
}
|
|
|
|
// 日志
|
|
writer := new(LogWriter)
|
|
writer.Init()
|
|
logs.SetWriter(writer)
|
|
|
|
// 运行主函数
|
|
main()
|
|
}
|
|
|
|
// 版本号
|
|
func (this *AppCmd) runVersion() {
|
|
fmt.Println(this.product+" v"+this.version, "(build: "+runtime.Version(), runtime.GOOS, runtime.GOARCH+")")
|
|
}
|
|
|
|
// 帮助
|
|
func (this *AppCmd) runHelp() {
|
|
this.Print()
|
|
}
|
|
|
|
// 启动
|
|
func (this *AppCmd) runStart() {
|
|
proc := this.checkPid()
|
|
if proc != nil {
|
|
fmt.Println(this.product+" already started, pid:", proc.Pid)
|
|
return
|
|
}
|
|
|
|
cmd := exec.Command(os.Args[0])
|
|
err := cmd.Start()
|
|
if err != nil {
|
|
fmt.Println(this.product+" start failed:", err.Error())
|
|
return
|
|
}
|
|
|
|
fmt.Println(this.product+" started ok, pid:", cmd.Process.Pid)
|
|
}
|
|
|
|
// 停止
|
|
func (this *AppCmd) runStop() {
|
|
proc := this.checkPid()
|
|
if proc == nil {
|
|
fmt.Println(this.product + " not started yet")
|
|
return
|
|
}
|
|
|
|
// 停止进程
|
|
_ = proc.Kill()
|
|
|
|
// 在Windows上经常不能及时释放资源
|
|
_ = DeletePid(Tea.Root + "/bin/pid")
|
|
fmt.Println(this.product+" stopped ok, pid:", proc.Pid)
|
|
}
|
|
|
|
// 重启
|
|
func (this *AppCmd) runRestart() {
|
|
this.runStop()
|
|
time.Sleep(1 * time.Second)
|
|
this.runStart()
|
|
}
|
|
|
|
// 状态
|
|
func (this *AppCmd) runStatus() {
|
|
proc := this.checkPid()
|
|
if proc == nil {
|
|
fmt.Println(this.product + " not started yet")
|
|
} else {
|
|
fmt.Println(this.product + " is running, pid: " + fmt.Sprintf("%d", proc.Pid))
|
|
}
|
|
}
|
|
|
|
// 检查PID
|
|
func (this *AppCmd) checkPid() *os.Process {
|
|
return CheckPid(Tea.Root + "/bin/pid")
|
|
}
|