@ -1,8 +1,9 @@
package main
package main
import (
import (
"flag"
"fmt"
"fmt"
"github.com/tint/env "
"github.com/rs/xid "
"hupeh.vip/pm/cmd"
"hupeh.vip/pm/cmd"
"hupeh.vip/pm/db"
"hupeh.vip/pm/db"
"os"
"os"
@ -10,86 +11,100 @@ import (
"strconv"
"strconv"
)
)
//import (
var allowPMTs = map [ string ] int {
// "flag"
"start" : 1 ,
// "fmt"
"restart" : 1 ,
// "log"
//"list": 1,
// "os"
//"shell": 1,
// "os/exec"
}
// "time"
//)
//
//// 移除不需要的参数
//func strip(slice []string, remove string) []string {
// for i := 0; i < len(slice); {
// if slice[i] == remove {
// if i != len(slice)-1 {
// slice = append(slice[:i], slice[i+1:]...)
// } else {
// slice = slice[:i]
// }
// } else {
// i++
// }
// }
// return slice
//}
//
//func subProcess(args []string) *exec.Cmd {
// cmd := exec.Command(args[0], args[1:]...)
// cmd.Stdin = os.Stdin
// cmd.Stdout = os.Stdout
// cmd.Stderr = os.Stderr
// err := cmd.Start()
// if err != nil {
// fmt.Fprintf(os.Stderr, "[-] Error: %s\n", err)
// }
// return cmd
//}
//
//func main() {
// daemon := flag.Bool("daemon", false, "run in daemon")
// forever := flag.Bool("forever", false, "run forever")
// flag.Parse()
//
// // 启用守护模式
// if *daemon {
// subProcess(strip(os.Arguments, "-daemon"))
// fmt.Printf("[*] Daemon running in pid: %d PPID: %d\n", os.Getpid(), os.Getppid())
// os.Exit(0)
// }
//
// if *forever {
// for {
// cmd := subProcess(strip(os.Arguments, "-forever"))
// fmt.Printf("[*] Forever running in pid: %d PPID: %d\n", os.Getpid(), os.Getppid())
// if err := cmd.Wait(); err != nil {
// fmt.Println(err)
// os.Exit(1)
// }
// }
// }
//
// fp, _ := os.OpenFile("./dosomething.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
// log.SetOutput(fp)
// log.Printf("[*] Service running in pid: %d PPID: %d\n", os.Getpid(), os.Getppid())
// defer log.Println("exit ...")
// for {
// log.Printf("DoSomething running in pid: %d PPID: %d\n", os.Getpid(), os.Getppid())
// time.Sleep(time.Second * 5)
// }
//}
func main ( ) {
func main ( ) {
env . Setup ( )
var sign string // all
var pmt string // all
var id int // start,restart
var daemon bool // start,restart
switch env . String ( "PMT_CURRENT_FUNCTION" ) {
flag . StringVar ( & sign , "sign" , "" , "sign token" )
case "start" :
flag . StringVar ( & pmt , "pmt" , "" , "task name" )
case "stop" :
flag . IntVar ( & id , "id" , 0 , "app id" )
case "shell" :
flag . BoolVar ( & daemon , "daemon" , false , "daemon mode" )
case "list" :
flag . Parse ( )
default :
// 命令行模式
if v , ok := allowPMTs [ pmt ] ; ! ok || v != 1 {
runCli ( )
runCli ( )
return
}
// 验证签名
if _ , err := xid . FromString ( sign ) ; err != nil {
fmt . Println ( cmd . Red ( "bad sign token" ) )
return
}
switch pmt {
// 启动应用
case "start" :
// 开启守护模式
if ! daemon {
subProcess ( append ( os . Args , "-daemon" ) ... )
fmt . Printf ( "[*] Daemon running in pid: %d PPID: %d\n" , os . Getpid ( ) , os . Getppid ( ) )
os . Exit ( 0 )
}
if id <= 0 {
fmt . Println ( cmd . Red ( "missing app id" ) )
return
}
// 查询 app
app , err := db . FindApp ( db . WithAppID ( uint ( id ) ) )
if err != nil {
fmt . Println ( cmd . Red ( "failed to find app" ) )
fmt . Println ( " " + cmd . Red ( err . Error ( ) ) )
return
}
// 创建进程处理器
proc := db . NewProc ( app )
// 忽略运行中的
if proc . IsAlive ( ) {
return
}
// 启动失败
if err = proc . Start ( ) ; err != nil {
fmt . Println ( cmd . Yellow ( app . Name ) + " - " + cmd . Red ( "start fail" ) )
fmt . Println ( " " + cmd . Red ( err . Error ( ) ) )
return
}
// 启动成功
fmt . Println ( cmd . Yellow ( app . Name ) + " - " + cmd . Green ( "start success" ) )
// 重启脚本
case "restart" :
// 开启守护模式
if ! daemon {
subProcess ( append ( os . Args , "-daemon" ) ... )
fmt . Printf ( "[*] Daemon running in pid: %d PPID: %d\n" , os . Getpid ( ) , os . Getppid ( ) )
os . Exit ( 0 )
}
if id <= 0 {
fmt . Println ( cmd . Red ( "missing app id" ) )
return
}
// 查询 app
app , err := db . FindApp ( db . WithAppID ( uint ( id ) ) )
if err != nil {
fmt . Println ( cmd . Red ( "failed to find app" ) )
fmt . Println ( " " + cmd . Red ( err . Error ( ) ) )
return
}
// 创建进程处理器
proc := db . NewProc ( app )
// 重启失败
if err = proc . Restart ( ) ; err != nil {
fmt . Println ( cmd . Yellow ( app . Name ) + " - " + cmd . Red ( "restart fail" ) )
fmt . Println ( " " + cmd . Red ( err . Error ( ) ) )
return
}
// 重启成功
fmt . Println ( cmd . Yellow ( app . Name ) + " - " + cmd . Green ( "restart success" ) )
}
}
}
}
@ -99,7 +114,7 @@ func runCli() {
Description ( "description" ) .
Description ( "description" ) .
// start 命令
// start 命令
Command ( "start" , "Start a program in daemon" ) .
Command ( "start" , "Start program(s) in daemon" ) .
Argument ( "[names:...string]" , "file/name/id" ) .
Argument ( "[names:...string]" , "file/name/id" ) .
Option ( "-w, --watch <watch:boolean>" , "Watches folder changes" ) .
Option ( "-w, --watch <watch:boolean>" , "Watches folder changes" ) .
Option ( "-c, --cwd <cwd:string>" , "Sets working directory " + cmd . Yellow ( "Sets working directory" ) + " Sets working directory " + cmd . Yellow ( "Sets working directory" ) + " Sets working directory " + cmd . Yellow ( " Sets working directory" ) + " Sets working directory " + cmd . Yellow ( "Sets working directory" ) + " Sets working directory " + cmd . Yellow ( "Sets working directory" ) + " End ..." ) .
Option ( "-c, --cwd <cwd:string>" , "Sets working directory " + cmd . Yellow ( "Sets working directory" ) + " Sets working directory " + cmd . Yellow ( "Sets working directory" ) + " Sets working directory " + cmd . Yellow ( " Sets working directory" ) + " Sets working directory " + cmd . Yellow ( "Sets working directory" ) + " Sets working directory " + cmd . Yellow ( "Sets working directory" ) + " End ..." ) .
@ -107,25 +122,31 @@ func runCli() {
Option ( "-e, --env" , "Sets current environment name" ) .
Option ( "-e, --env" , "Sets current environment name" ) .
Option ( "-i, --interpreter" , "Sets interpreter name" ) .
Option ( "-i, --interpreter" , "Sets interpreter name" ) .
Action ( func ( c * cmd . Command , m map [ string ] any , a ... any ) error {
Action ( func ( c * cmd . Command , m map [ string ] any , a ... any ) error {
var apps [ ] * db . App
var err error
if len ( a ) != 1 {
if len ( a ) != 1 {
return c . ShowHelp ( )
apps , err = db . FindApps ( db . WithAppStatus ( db . StatusStopped ) )
if err != nil {
fmt . Println ( cmd . Red ( "load all apps fail" ) )
fmt . Println ( " " + cmd . Red ( err . Error ( ) ) )
return err
}
}
} else {
var apps [ ] * db . App
scripts := a [ 0 ] . ( [ ] string )
scripts := a [ 0 ] . ( [ ] string )
for _ , script := range scripts {
for _ , script := range scripts {
loads , err := db . ParseInput ( script )
loads , err := db . ParseInput ( script )
if err != nil {
if err != nil {
fmt . Println ( cmd . Red ( "load all apps fail" ) )
fmt . Println ( " " + cmd . Red ( err . Error ( ) ) )
return err
return err
}
}
apps = append ( apps , loads ... )
apps = append ( apps , loads ... )
}
}
}
if len ( apps ) == 0 {
if len ( apps ) == 0 {
fmt . Println ( "No app found" )
fmt . Println ( "No app found" )
return nil
return nil
}
}
for _ , app := range apps {
for _ , app := range apps {
if app . Status == db . StatusRunning {
if app . Status == db . StatusRunning {
fmt . Println ( cmd . Yellow ( app . Name ) , cmd . Green ( "running" ) )
fmt . Println ( cmd . Yellow ( app . Name ) , cmd . Green ( "running" ) )
@ -133,16 +154,74 @@ func runCli() {
}
}
if app . ID == 0 {
if app . ID == 0 {
if err := db . SaveApp ( app ) ; err != nil {
if err := db . SaveApp ( app ) ; err != nil {
fmt . Println ( cmd . Yellow ( app . Name ) , cmd . Red ( "failed for save" ) )
fmt . Println ( cmd . Yellow ( app . Name ) , cmd . Red ( "failed to saving" ) )
fmt . Println ( " " + cmd . Red ( err . Error ( ) ) )
continue
}
}
// todo options
proc := subProcess (
"-id=" + strconv . Itoa ( int ( app . ID ) ) ,
"-pmt=start" ,
"-sign=" + xid . New ( ) . String ( ) ,
)
if err := proc . Wait ( ) ; err != nil {
fmt . Println ( cmd . Yellow ( app . Name ) , cmd . Red ( "failed" ) )
fmt . Println ( " " , err . Error ( ) )
} else {
fmt . Println ( cmd . Yellow ( app . Name ) , cmd . Green ( "success" ) )
}
}
fmt . Println ( "over" )
return nil
} ) .
// restart 命令
Command ( "restart" , "Restarts program(s)" ) .
Argument ( "<names:...string>" , "file/name/id" ) .
Action ( func ( c * cmd . Command , m map [ string ] any , a ... any ) error {
var apps [ ] * db . App
if len ( a ) != 0 {
c . ShowHelp ( )
return nil
}
scripts := a [ 0 ] . ( [ ] string )
for _ , script := range scripts {
loads , err := db . ParseInput ( script )
if err != nil {
fmt . Println ( cmd . Red ( "load all apps fail" ) )
fmt . Println ( " " + cmd . Red ( err . Error ( ) ) )
return err
return err
}
}
apps = append ( apps , loads ... )
}
if len ( apps ) == 0 {
fmt . Println ( "No app found" )
return nil
}
for _ , app := range apps {
if app . ID == 0 {
if err := db . SaveApp ( app ) ; err != nil {
fmt . Println ( cmd . Yellow ( app . Name ) , cmd . Red ( "failed to saving" ) )
fmt . Println ( " " + cmd . Red ( err . Error ( ) ) )
continue
}
}
}
if err := runStart ( app . ID ) ; err != nil {
// todo options
proc := subProcess (
"-id=" + strconv . Itoa ( int ( app . ID ) ) ,
"-pmt=restart" ,
"-sign=" + xid . New ( ) . String ( ) ,
)
if err := proc . Wait ( ) ; err != nil {
fmt . Println ( cmd . Yellow ( app . Name ) , cmd . Red ( "failed" ) )
fmt . Println ( cmd . Yellow ( app . Name ) , cmd . Red ( "failed" ) )
fmt . Println ( " " , err . Error ( ) )
fmt . Println ( " " , err . Error ( ) )
} else {
fmt . Println ( cmd . Yellow ( app . Name ) , cmd . Green ( "success" ) )
}
}
}
}
fmt . Println ( "over" )
fmt . Println ( "over" )
return nil
return nil
} ) .
} ) .
@ -150,8 +229,38 @@ func runCli() {
Command ( "stop" , "Stops a program" ) .
Command ( "stop" , "Stops a program" ) .
Argument ( "<names:...string>" , "file/name/id" ) .
Argument ( "<names:...string>" , "file/name/id" ) .
Action ( func ( c * cmd . Command , m map [ string ] any , a ... any ) error {
Action ( func ( c * cmd . Command , m map [ string ] any , a ... any ) error {
fmt . Println ( "停止程序" )
if len ( a ) != 1 {
fmt . Println ( a ... )
return c . ShowHelp ( )
}
var apps [ ] * db . App
scripts := a [ 0 ] . ( [ ] string )
for _ , script := range scripts {
loads , err := db . ParseInput ( script )
if err != nil {
return err
}
apps = append ( apps , loads ... )
}
if len ( apps ) == 0 {
fmt . Println ( "No app found" )
return nil
}
for _ , app := range apps {
if app . PID <= 0 {
fmt . Println ( cmd . Yellow ( app . Name ) , "not running" )
return nil
}
proc := db . NewProc ( app )
err := proc . Stop ( )
if err != nil {
fmt . Println ( cmd . Yellow ( app . Name ) , cmd . Red ( "failed to stop" ) )
fmt . Println ( " " + cmd . Red ( err . Error ( ) ) )
return err
}
fmt . Println ( cmd . Yellow ( app . Name ) , cmd . Green ( "stopped" ) )
return nil
}
fmt . Println ( "over" )
return nil
return nil
} ) .
} ) .
@ -159,17 +268,8 @@ func runCli() {
Run ( )
Run ( )
}
}
func runStart ( id uint ) error {
func subProcess ( args ... string ) * exec . Cmd {
proc := subProcess (
cmd := exec . Command ( os . Args [ 0 ] , args ... )
[ ] string { os . Args [ 0 ] , "-id" , strconv . Itoa ( int ( id ) ) } ,
[ ] string { "PMT_CURRENT_FUNCTION=start" } ,
)
return proc . Wait ( )
}
func subProcess ( args [ ] string , env [ ] string ) * exec . Cmd {
cmd := exec . Command ( args [ 0 ] , args [ 1 : ] ... )
cmd . Env = append ( os . Environ ( ) , env ... )
cmd . Stdin = os . Stdin
cmd . Stdin = os . Stdin
cmd . Stdout = os . Stdout
cmd . Stdout = os . Stdout
cmd . Stderr = os . Stderr
cmd . Stderr = os . Stderr