/* * Copyright (c) 2019 Huawei Technologies Co., Ltd. * A-Tune is licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. * You may obtain a copy of Mulan PSL v1 at: * http://license.coscl.org.cn/MulanPSL * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR * PURPOSE. * See the Mulan PSL v1 for more details. * Create: 2019-10-29 */ package pyservice import ( "atune/common/config" "atune/common/log" "atune/common/registry" "bufio" "fmt" "io" "os" "os/exec" "os/signal" "path" "strings" "syscall" ) func init() { registry.RegisterDaemonService("pyengine", &PyEngine{}) } // PyEngine : the struct store the pyEngine conf type PyEngine struct { Cfg *config.Cfg } // Init method init the PyEngine service func (p *PyEngine) Init() error { return nil } // Set the config of the monitor func (p *PyEngine) Set(cfg *config.Cfg) { p.Cfg = cfg } // Run method start the python service func (p *PyEngine) Run() error { cmdSlice := make([]string, 0) cmdSlice = append(cmdSlice, "python3") cmdSlice = append(cmdSlice, path.Join(config.DefaultAnalysisPath, "app.py")) cmdSlice = append(cmdSlice, path.Join(config.DefaultConfPath, "atuned.cnf")) cmdStr := strings.Join(cmdSlice, " ") cmd := exec.Command("sh", "-c", cmdStr) cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} stdout, err := cmd.StdoutPipe() stderr, err := cmd.StderrPipe() go listenToSystemSignals(cmd) go logStdout(stdout) go logStderr(stderr) err = cmd.Start() if err != nil { return fmt.Errorf("cmd.Start() analysis service faild: %v", err) os.Exit(-1) } err = cmd.Wait() if err != nil { log.Errorf("cmd.Run() analysis faild with: %v", err) os.Exit(-1) } return nil } func logStdout(stdout io.ReadCloser) { scanner := bufio.NewScanner(stdout) for scanner.Scan() { line := scanner.Text() log.Debug(line) } } func logStderr(stderr io.ReadCloser) { scanner := bufio.NewScanner(stderr) for scanner.Scan() { line := scanner.Text() log.Debug(line) } } func listenToSystemSignals(cmd *exec.Cmd) { signalChan := make(chan os.Signal, 1) signal.Notify(signalChan, os.Interrupt, os.Kill, syscall.SIGKILL) select { case <-signalChan: syscall.Kill(-cmd.Process.Pid, syscall.SIGKILL) os.Exit(-1) } }