From 380586fb73783fa995cb6cdebbbe075aae16d084 Mon Sep 17 00:00:00 2001 From: mountain Date: Thu, 22 Aug 2024 11:28:58 +0900 Subject: [PATCH] =?UTF-8?q?=EB=A1=9C=EA=B7=B8=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=EC=9D=84=20houston=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/client.go | 28 +++++----- client/operation.go | 126 ++++++++++++++++---------------------------- shared/operator.go | 9 ++-- 3 files changed, 66 insertions(+), 97 deletions(-) diff --git a/client/client.go b/client/client.go index ed3d1f7..a0ec21a 100644 --- a/client/client.go +++ b/client/client.go @@ -33,10 +33,11 @@ import ( ) type runcommand struct { - Exec string `json:"exec"` - Args []string `json:"args"` - Version string `json:"version"` - AutoRestart bool `json:"auto_restart"` + Exec string `json:"exec"` + Args []string `json:"args"` + Version string `json:"version"` + AutoRestart bool `json:"auto_restart"` + OutputLogFile string `json:"logfile"` } type easyruncommand runcommand @@ -99,6 +100,7 @@ type procmeta struct { recover bool state int32 stdin io.WriteCloser + logfile string } func (pm *procmeta) isState(s protos.ProcessState) bool { @@ -493,10 +495,11 @@ func NewClient(standalone bool) (HoustonClient, error) { if found.recover { time.Sleep(time.Second) sr := shared.StartProcessRequest{ - Name: found.name, - Version: found.version, - Args: found.args, - AutoRestart: found.recover, + Name: found.name, + Version: found.version, + Args: found.args, + AutoRestart: found.recover, + OutputLogFile: found.logfile, } if err := hc.startChildProcess(&sr); err != nil { @@ -583,10 +586,11 @@ func (hc *houstonClient) Start() { // service 서비스 for i := 0; i < count; i++ { sr := shared.StartProcessRequest{ - Name: service, - Version: cmd.Version, - Args: append([]string{cmd.Exec}, cmd.Args...), - AutoRestart: cmd.AutoRestart, + Name: service, + Version: cmd.Version, + Args: append([]string{cmd.Exec}, cmd.Args...), + AutoRestart: cmd.AutoRestart, + OutputLogFile: cmd.OutputLogFile, } if err := hc.startChildProcess(&sr); err != nil { diff --git a/client/operation.go b/client/operation.go index 10a2ad8..6687ce6 100644 --- a/client/operation.go +++ b/client/operation.go @@ -220,37 +220,12 @@ func prepareProcessLaunch(storageRoot string, req *shared.StartProcessRequest) ( verpath: verpath, state: int32(protos.ProcessState_Stopped), stdin: stdin, + logfile: req.OutputLogFile, }, nil } return nil, errors.New("not found") } -func makeLogFilePrefix(meta *procmeta, index int) string { - now := time.Now().UTC() - ext := path.Ext(meta.args[0]) - nameonly := path.Base(filepath.ToSlash(meta.args[0])) - if len(ext) > 0 { - nameonly = nameonly[:len(nameonly)-len(ext)] - } - ts := now.Format("2006-01-02T15-04-05") - if index == 0 { - - return path.Join(meta.verpath, "logs", fmt.Sprintf("%s_%s", nameonly, ts)) - } - - return path.Join(meta.verpath, "logs", fmt.Sprintf("%s_%d_%s", nameonly, index, ts)) -} - -func evaluateExpression(expression string, params map[string]any) (any, error) { - expression = strings.TrimSpace(expression) - expr, err := govaluate.NewEvaluableExpression(expression) - if err != nil { - return 0, err - } - - return expr.Evaluate(params) -} - func evaluateArgs(args []string, params map[string]any) ([]string, error) { re := regexp.MustCompile(`\$\(\((.*?)\)\)`) @@ -314,7 +289,7 @@ func (hc *houstonClient) launch(meta *procmeta) error { return err } - stdReader := func(jobName string, r io.ReadCloser, index int) { + stdReader := func(jobName string, r io.ReadCloser, index int, logfile string) { defer func() { reco := recover() if reco != nil { @@ -335,62 +310,30 @@ func (hc *houstonClient) launch(meta *procmeta) error { defer r.Close() reader := bufio.NewReader(r) - thisFileSize := 0 - logFileIndex := 0 - var logWriter func([]byte) - if *logger.UseLogFile { - logFileNamePrefix := makeLogFilePrefix(meta, index) - logFileName := fmt.Sprintf("%s_%d.log", logFileNamePrefix, logFileIndex) - targetFile, err := os.Create(logFileName) - if err != nil { - logger.Println("failed to create log file :", logFileName) - return - } - - exef, _ := os.Executable() - var linkPath string - if index == 0 { - linkPath = path.Join(path.Dir(exef), path.Dir(logFileName), meta.name+".log") - } else { - linkPath = path.Join(path.Dir(exef), path.Dir(logFileName), fmt.Sprintf("%s_%d.log", meta.name, index)) - } - - os.Remove(linkPath) - os.Symlink(path.Base(filepath.ToSlash(targetFile.Name())), linkPath) - - defer func() { - if targetFile != nil { - targetFile.Close() - } - }() - - logWriter = func(buff []byte) { - for written := 0; written < len(buff); { - n, err := targetFile.Write(buff) - if err != nil { - logger.Println("write log file failed :", logFileName, err) - break - } else { - written += n - thisFileSize += n - } - } - - if thisFileSize > 5*1024*1024 { - logFileIndex++ - logFileName = fmt.Sprintf("%s_%d.log", logFileNamePrefix, logFileIndex) - nextTargetFile, err := os.Create(logFileName) - if err != nil { - logger.Println("failed to create log file :", logFileName) - } else { + if len(logfile) > 0 { + logfilePath := path.Join("logs", logfile) + targetFile, err := os.OpenFile(logfilePath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0666) + if err == nil && targetFile != nil { + defer func() { + if targetFile != nil { targetFile.Close() - targetFile = nextTargetFile - os.Remove(linkPath) - os.Symlink(path.Base(filepath.ToSlash(targetFile.Name())), linkPath) - thisFileSize = 0 + } + }() + + logWriter = func(buff []byte) { + for written := 0; written < len(buff); { + n, err := targetFile.Write(buff) + if err != nil { + logger.Println("write log file failed :", logfilePath, err) + break + } else { + written += n + } } } + } else { + logger.Println("failed to create log file :", logfilePath) } } else { logWriter = func(buff []byte) { @@ -487,14 +430,35 @@ func (hc *houstonClient) launch(meta *procmeta) error { } } - go stdReader(meta.name, stdout, index) + // 자체 환경 변수 + customEnv := map[string]string{ + "HOUSTON_SIBLIING_INDEX": fmt.Sprintf("%d", index), + "HOUSTON_PROC_TIMESTAMP": time.Now().UTC().Format("2006-01-02T15-04-05"), + } - meta.cmd.Env = append(os.Environ(), fmt.Sprintf("HOUSTON_SIBLIING_INDEX=%d", index)) + // 프로세스 환경 변수에 반영 + meta.cmd.Env = os.Environ() + for k, v := range customEnv { + meta.cmd.Env = append(meta.cmd.Env, fmt.Sprintf("%s=%s", k, v)) + } + + // argument 표현식 계산 meta.cmd.Args, err = evaluateArgs(meta.cmd.Args, parseEnv(meta.cmd.Env)) if err != nil { logger.Println("evaluateArgs failed :", err) return err } + + // 로그파일에 환경변수 적용 + evalfile := os.Expand(meta.logfile, func(n string) string { + v := os.Getenv(n) + if len(v) == 0 { + return customEnv[n] + } + return v + }) + + go stdReader(meta.name, stdout, index, evalfile) logger.Println("startChildProcess :", meta.cmd.Args) err = meta.cmd.Start() diff --git a/shared/operator.go b/shared/operator.go index e702e68..49877a5 100644 --- a/shared/operator.go +++ b/shared/operator.go @@ -27,10 +27,11 @@ type WithdrawRequest struct { } type StartProcessRequest struct { - Name string - Version string - Args []string - AutoRestart bool + Name string + Version string + Args []string + AutoRestart bool + OutputLogFile string } type StopProcessRequest struct {