Skip to content

feat: support change the working directory #67

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions lib/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down
12 changes: 9 additions & 3 deletions lib/master/master.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -149,7 +153,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{
Expand All @@ -159,6 +163,7 @@ func (master *Master) Prepare(sourcePath string, name string, language string, k
Language: language,
KeepAlive: keepAlive,
Args: args,
Cwd: cwd,
}
} else {
procPreparable = &preparable.Preparable{
Expand All @@ -168,6 +173,7 @@ func (master *Master) Prepare(sourcePath string, name string, language string, k
Language: language,
KeepAlive: keepAlive,
Args: args,
Cwd: cwd,
}
}

Expand Down
6 changes: 4 additions & 2 deletions lib/master/remote_master.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -176,14 +177,15 @@ 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,
Name: name,
KeepAlive: keepAlive,
Args: args,
BinFile: binFile,
Cwd: cwd,
}

return client.conn.Call("RemoteMaster.StartGoBin", goBin, &started)
Expand Down
4 changes: 4 additions & 0 deletions lib/preparable/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type Preparable struct {
Name string
SourcePath string
Cmd string
Cwd string
SysFolder string
Language string
KeepAlive bool
Expand All @@ -39,6 +40,7 @@ type BinaryPreparable struct {
Name string
SourcePath string
Cmd string
Cwd string
SysFolder string
Language string
KeepAlive bool
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand Down
7 changes: 5 additions & 2 deletions lib/process/proc_container.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type ProcContainer interface {
type Proc struct {
Name string
Cmd string
Cwd string
Args []string
Path string
Pidfile string
Expand All @@ -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,
Expand Down
15 changes: 15 additions & 0 deletions lib/utils/file_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package utils
import (
"io/ioutil"
"os"
"path"

"github.com/BurntSushi/toml"
)
Expand All @@ -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)
}

Expand Down
64 changes: 49 additions & 15 deletions pmgo.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ 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"

"os"
"os/signal"
"path"
"path/filepath"
"syscall"

"fmt"
Expand All @@ -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.")

Expand All @@ -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.")
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -146,17 +146,51 @@ 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)
configFile := os.Getenv("PMGO_CONFIG_FILE")
if configFile != "" {
*serveConfigFile = configFile
} else {
folderPath := os.Getenv("HOME")
*serveConfigFile = folderPath + "/.pmgo/config.toml"
}
}

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: path.Join(filepath.Dir(*serveConfigFile), "main.pid"),
ctx = &daemon.Context{
PidFileName: decodableMaster.PidFile,
PidFilePerm: 0644,
LogFileName: path.Join(filepath.Dir(*serveConfigFile), "main.log"),
LogFileName: decodableMaster.OutFile,
LogFilePerm: 0640,
WorkDir: "./",
Umask: 027,
Expand Down