From a73342e645e704771e4080554bdfb76e547bb5ee Mon Sep 17 00:00:00 2001 From: youjianglong Date: Sat, 25 Dec 2021 16:47:17 +0800 Subject: [PATCH 1/3] feat: support change the working directory --- lib/cli/cli.go | 4 ++-- lib/master/master.go | 4 +++- lib/master/remote_master.go | 6 ++++-- lib/preparable/process.go | 4 ++++ lib/process/proc_container.go | 7 +++++-- pmgo.go | 16 ++++++++-------- 6 files changed, 26 insertions(+), 15 deletions(-) diff --git a/lib/cli/cli.go b/lib/cli/cli.go index 078c285..72955bb 100644 --- a/lib/cli/cli.go +++ b/lib/cli/cli.go @@ -40,8 +40,8 @@ func (cli *Cli) Save() { // StartGoBin will try to start a go binary process. // Returns a fatal error in case there's any. -func (cli *Cli) StartGoBin(sourcePath string, name string, keepAlive bool, args []string, binFile bool) { - err := cli.remoteClient.StartGoBin(sourcePath, name, keepAlive, args, binFile) +func (cli *Cli) StartGoBin(sourcePath string, name string, keepAlive bool, args []string, cwd string, binFile bool) { + err := cli.remoteClient.StartGoBin(sourcePath, name, keepAlive, args, cwd, binFile) if err != nil { log.Fatalf("Failed to start go bin due to: %+v\n", err) } diff --git a/lib/master/master.go b/lib/master/master.go index a235fb0..2bc6d0a 100644 --- a/lib/master/master.go +++ b/lib/master/master.go @@ -149,7 +149,7 @@ func (master *Master) WatchProcs() { // Prepare will compile the source code into a binary and return a preparable // ready to be executed. -func (master *Master) Prepare(sourcePath string, name string, language string, keepAlive bool, args []string, fromBin bool) (preparable.ProcPreparable, []byte, error) { +func (master *Master) Prepare(sourcePath string, name string, language string, keepAlive bool, args []string, cwd string, fromBin bool) (preparable.ProcPreparable, []byte, error) { var procPreparable preparable.ProcPreparable if fromBin { procPreparable = &preparable.BinaryPreparable{ @@ -159,6 +159,7 @@ func (master *Master) Prepare(sourcePath string, name string, language string, k Language: language, KeepAlive: keepAlive, Args: args, + Cwd: cwd, } } else { procPreparable = &preparable.Preparable{ @@ -168,6 +169,7 @@ func (master *Master) Prepare(sourcePath string, name string, language string, k Language: language, KeepAlive: keepAlive, Args: args, + Cwd: cwd, } } diff --git a/lib/master/remote_master.go b/lib/master/remote_master.go index 4eb016a..4c263b2 100644 --- a/lib/master/remote_master.go +++ b/lib/master/remote_master.go @@ -26,6 +26,7 @@ type GoBin struct { Name string // Name is the process name that will be given to the process. KeepAlive bool // KeepAlive will determine whether pmgo should keep the proc live or not. Args []string // Args is an array containing all the extra args that will be passed to the binary after compilation. + Cwd string // Change the working directory BinFile bool } @@ -67,7 +68,7 @@ func (remote_master *RemoteMaster) StartGoBin(goBin *GoBin, ack *bool) error { if goBin.BinFile { isFromBinFile = true } - preparable, output, err := remote_master.master.Prepare(goBin.SourcePath, goBin.Name, "go", goBin.KeepAlive, goBin.Args, isFromBinFile) + preparable, output, err := remote_master.master.Prepare(goBin.SourcePath, goBin.Name, "go", goBin.KeepAlive, goBin.Args, goBin.Cwd, isFromBinFile) *ack = true if err != nil { return fmt.Errorf("ERROR: %s OUTPUT: %s", err, string(output)) @@ -176,7 +177,7 @@ func (client *RemoteClient) Save() error { // StartGoBin is a wrapper that calls the remote StartsGoBin. // It returns an error in case there's any. -func (client *RemoteClient) StartGoBin(sourcePath string, name string, keepAlive bool, args []string, binFile bool) error { +func (client *RemoteClient) StartGoBin(sourcePath string, name string, keepAlive bool, args []string, cwd string, binFile bool) error { var started bool goBin := &GoBin{ SourcePath: sourcePath, @@ -184,6 +185,7 @@ func (client *RemoteClient) StartGoBin(sourcePath string, name string, keepAlive KeepAlive: keepAlive, Args: args, BinFile: binFile, + Cwd: cwd, } return client.conn.Call("RemoteMaster.StartGoBin", goBin, &started) diff --git a/lib/preparable/process.go b/lib/preparable/process.go index 25919bd..d974cd3 100644 --- a/lib/preparable/process.go +++ b/lib/preparable/process.go @@ -29,6 +29,7 @@ type Preparable struct { Name string SourcePath string Cmd string + Cwd string SysFolder string Language string KeepAlive bool @@ -39,6 +40,7 @@ type BinaryPreparable struct { Name string SourcePath string Cmd string + Cwd string SysFolder string Language string KeepAlive bool @@ -84,6 +86,7 @@ func (preparable *Preparable) Start() (process.ProcContainer, error) { proc := &process.Proc{ Name: preparable.Name, Cmd: preparable.Cmd, + Cwd: preparable.Cwd, Args: preparable.Args, Path: preparable.getPath(), Pidfile: preparable.getPidPath(), @@ -154,6 +157,7 @@ func (preparable *BinaryPreparable) Start() (process.ProcContainer, error) { proc := &process.Proc{ Name: preparable.Name, Cmd: preparable.Cmd, + Cwd: preparable.Cwd, Args: preparable.Args, Path: preparable.getPath(), Pidfile: preparable.getPidPath(), diff --git a/lib/process/proc_container.go b/lib/process/proc_container.go index 9e964d7..56138d3 100644 --- a/lib/process/proc_container.go +++ b/lib/process/proc_container.go @@ -40,6 +40,7 @@ type ProcContainer interface { type Proc struct { Name string Cmd string + Cwd string Args []string Path string Pidfile string @@ -63,9 +64,11 @@ func (proc *Proc) Start() error { if err != nil { return err } - wd, _ := os.Getwd() + if proc.Cwd == "" { + proc.Cwd, _ = os.Getwd() + } procAtr := &os.ProcAttr{ - Dir: wd, + Dir: proc.Cwd, Env: os.Environ(), Files: []*os.File{ os.Stdin, diff --git a/pmgo.go b/pmgo.go index 19e6340..68ea46e 100644 --- a/pmgo.go +++ b/pmgo.go @@ -46,15 +46,14 @@ import ( ) var ( - app = kingpin.New("pmgo", "Aguia Process Manager.") - dns = app.Flag("dns", "TCP Dns host.").Default(":9876").String() - timeout = 30 * time.Second + app = kingpin.New("pmgo", "Aguia Process Manager.") + serveConfigFile = app.Flag("config-file", "Config file location").String() + dns = app.Flag("dns", "TCP Dns host.").Default(":9876").String() + timeout = 30 * time.Second - serveStop = app.Command("kill", "Kill daemon pmgo.") - serveStopConfigFile = serveStop.Flag("config-file", "Config file location").String() + serveStop = app.Command("kill", "Kill daemon pmgo.") - serve = app.Command("serve", "Create pmgo daemon.") - serveConfigFile = serve.Flag("config-file", "Config file location").String() + serve = app.Command("serve", "Create pmgo daemon.") resurrect = app.Command("resurrect", "Resurrect all previously save processes.") @@ -63,6 +62,7 @@ var ( startName = start.Arg("name", "Process name.").Required().String() binFile = start.Arg("binary", "compiled golang file").Bool() startKeepAlive = true + startCwd = start.Flag("cwd", "Change the working directory").String() startArgs = start.Flag("args", "External args.").Strings() restart = app.Command("restart", "Restart a process.") @@ -100,7 +100,7 @@ func main() { case start.FullCommand(): checkRemoteMasterServer() cli := cli.InitCli(*dns, timeout) - cli.StartGoBin(*startSourcePath, *startName, startKeepAlive, *startArgs, *binFile) + cli.StartGoBin(*startSourcePath, *startName, startKeepAlive, *startArgs, *startCwd, *binFile) cli.Status() case restart.FullCommand(): checkRemoteMasterServer() From ea423f1b441e93c8f1fe313ed58db8a3b640d1f1 Mon Sep 17 00:00:00 2001 From: youjianglong Date: Sat, 25 Dec 2021 19:40:14 +0800 Subject: [PATCH 2/3] fix: Optimize directory processing --- lib/master/master.go | 8 ++++++-- lib/utils/file_util.go | 15 +++++++++++++++ pmgo.go | 39 ++++++++++++++++++++++++++++++++++----- 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/lib/master/master.go b/lib/master/master.go index 2bc6d0a..ba60ead 100644 --- a/lib/master/master.go +++ b/lib/master/master.go @@ -96,8 +96,12 @@ func InitMaster(configFile string) *Master { master.SysFolder = path.Dir(configFile) + "/" } master.Watcher = watcher - master.Revive() - log.Infof("All procs revived...") + err = master.Revive() + if err != nil { + log.Error(err) + } else { + log.Infof("All procs revived...") + } go master.WatchProcs() // go master.SaveProcsLoop() go master.UpdateStatus() diff --git a/lib/utils/file_util.go b/lib/utils/file_util.go index 96e542c..7473896 100644 --- a/lib/utils/file_util.go +++ b/lib/utils/file_util.go @@ -3,6 +3,7 @@ package utils import ( "io/ioutil" "os" + "path" "github.com/BurntSushi/toml" ) @@ -11,12 +12,26 @@ import ( // permission mode to 0660 // Returns an error in case there's any. func WriteFile(filepath string, b []byte) error { + dir := path.Dir(filepath) + if _, err := os.Stat(dir); os.IsNotExist(err) { + err = os.MkdirAll(dir, 0755) + if err != nil { + return err + } + } return ioutil.WriteFile(filepath, b, 0660) } // GetFile will open filepath. // Returns a tuple with a file and an error in case there's any. func GetFile(filepath string) (*os.File, error) { + dir := path.Dir(filepath) + if _, err := os.Stat(dir); os.IsNotExist(err) { + err = os.MkdirAll(dir, 0755) + if err != nil { + return nil, err + } + } return os.OpenFile(filepath, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0777) } diff --git a/pmgo.go b/pmgo.go index 68ea46e..8cced51 100644 --- a/pmgo.go +++ b/pmgo.go @@ -28,6 +28,7 @@ import ( "github.com/struCoder/pmgo/lib/cli" "github.com/struCoder/pmgo/lib/master" + "github.com/struCoder/pmgo/lib/utils" "gopkg.in/alecthomas/kingpin.v2" "github.com/sevlyar/go-daemon" @@ -35,7 +36,6 @@ import ( "os" "os/signal" "path" - "path/filepath" "syscall" "fmt" @@ -146,17 +146,46 @@ func isDaemonRunning(ctx *daemon.Context) (bool, *os.Process, error) { return true, d, nil } +var ctx *daemon.Context + func getCtx() *daemon.Context { + if ctx != nil { + return ctx + } if *serveConfigFile == "" { folderPath := os.Getenv("HOME") *serveConfigFile = folderPath + "/.pmgo/config.toml" - os.MkdirAll(path.Dir(*serveConfigFile), 0755) } - ctx := &daemon.Context{ - PidFileName: path.Join(filepath.Dir(*serveConfigFile), "main.pid"), + dir := path.Dir(*serveConfigFile) + os.MkdirAll(dir, 0755) + + decodableMaster := master.DecodableMaster{} + err := utils.SafeReadTomlFile(*serveConfigFile, &decodableMaster) + if err != nil && !os.IsNotExist(err) { + panic(err) + } + + if decodableMaster.SysFolder != "" { + dir = decodableMaster.SysFolder + } + + if decodableMaster.PidFile == "" { + decodableMaster.PidFile = path.Join(dir, "main.pid") + } else { + os.MkdirAll(path.Dir(decodableMaster.PidFile), 0755) + } + + if decodableMaster.OutFile == "" { + decodableMaster.OutFile = path.Join(dir, "main.log") + } else { + os.MkdirAll(path.Dir(decodableMaster.OutFile), 0755) + } + + ctx = &daemon.Context{ + PidFileName: decodableMaster.PidFile, PidFilePerm: 0644, - LogFileName: path.Join(filepath.Dir(*serveConfigFile), "main.log"), + LogFileName: decodableMaster.OutFile, LogFilePerm: 0640, WorkDir: "./", Umask: 027, From 492ba1a17de9afbfeec2a0b35aeed0aab1eda63b Mon Sep 17 00:00:00 2001 From: youjianglong Date: Mon, 27 Dec 2021 09:58:13 +0800 Subject: [PATCH 3/3] feat: add server config file env PMGO_CONFIG_FILE --- pmgo.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pmgo.go b/pmgo.go index 8cced51..6710af8 100644 --- a/pmgo.go +++ b/pmgo.go @@ -153,8 +153,13 @@ func getCtx() *daemon.Context { return ctx } if *serveConfigFile == "" { - folderPath := os.Getenv("HOME") - *serveConfigFile = folderPath + "/.pmgo/config.toml" + configFile := os.Getenv("PMGO_CONFIG_FILE") + if configFile != "" { + *serveConfigFile = configFile + } else { + folderPath := os.Getenv("HOME") + *serveConfigFile = folderPath + "/.pmgo/config.toml" + } } dir := path.Dir(*serveConfigFile)