コード例 #1
0
ファイル: fsm.go プロジェクト: codeskyblue/gosuv
func (p *Process) startCommand() {
	// p.Stdout.Reset()
	// p.Stderr.Reset()
	// p.Output.Reset() // Donot reset because log is still needed.
	log.Printf("start cmd(%s): %s", p.Name, p.Command)
	p.cmd = p.buildCommand()

	p.SetState(Running)
	if err := p.cmd.Start(); err != nil {
		log.Warnf("program %s start failed: %v", p.Name, err)
		p.SetState(Fatal)
		return
	}
	go func() {
		errC := GoFunc(p.cmd.Wait)
		startTime := time.Now()
		select {
		case <-errC:
			// if p.cmd.Wait() returns, it means program and its sub process all quited. no need to kill again
			// func Wait() will only return when program session finishs. (Only Tested on mac)
			log.Printf("program(%s) finished, time used %v", p.Name, time.Since(startTime))
			if time.Since(startTime) < time.Duration(p.StartSeconds)*time.Second {
				if p.retryLeft == p.StartRetries { // If first time quit so fast, just set to fatal
					p.SetState(Fatal)
					log.Printf("program(%s) exit too quick, status -> fatal", p.Name)
					return
				}
			}
			p.waitNextRetry()
		case <-p.stopC:
			log.Println("recv stop command")
			p.stopCommand() // clean up all process
		}
	}()
}
コード例 #2
0
ファイル: config.go プロジェクト: millken/ydaemon
func configReader(fileName string) error {

	stat, err := os.Stat(fileName)
	if err != nil {
		log.Printf("Failed to find config file: %s\n", err)
		return err
	}

	if !stat.ModTime().After(lastReadConfig) {
		return err
	}

	lastReadConfig = time.Now()

	log.Printf("Loading config: %s\n", fileName)

	cfg := new(AppConfig)

	err = gcfg.ReadFileInto(cfg, fileName)
	if err != nil {
		log.Printf("Failed to parse config data: %s\n", err)
		return err
	}

	//cfg.Flags.HasStatHat = len(cfg.StatHat.ApiKey) > 0

	// log.Println("STATHAT APIKEY:", cfg.StatHat.ApiKey)
	// log.Println("STATHAT FLAG  :", cfg.Flags.HasStatHat)

	Config = cfg
	go startWorker()
	return nil
}
コード例 #3
0
ファイル: fsm.go プロジェクト: codeskyblue/gosuv
func (p *Process) stopCommand() {
	p.mu.Lock()
	defer p.mu.Unlock()
	defer p.SetState(Stopped)
	if p.cmd == nil {
		return
	}
	p.SetState(Stopping)
	if p.cmd.Process != nil {
		p.cmd.Process.Signal(syscall.SIGTERM) // TODO(ssx): add it to config
	}
	select {
	case <-GoFunc(p.cmd.Wait):
		log.Printf("program(%s) quit normally", p.Name)
	case <-time.After(time.Duration(p.StopTimeout) * time.Second): // TODO: add 3s to config
		log.Printf("program(%s) terminate all", p.Name)
		p.cmd.Terminate(syscall.SIGKILL) // cleanup
	}
	err := p.cmd.Wait() // This is OK, because Signal KILL will definitely work
	prefixStr := "\n--- GOSUV LOG " + time.Now().Format("2006-01-02 15:04:05")
	if err == nil {
		io.WriteString(p.cmd.Stderr, fmt.Sprintf("%s exit success ---\n\n", prefixStr))
	} else {
		io.WriteString(p.cmd.Stderr, fmt.Sprintf("%s exit %v ---\n\n", prefixStr, err))
	}
	if p.OutputFile != nil {
		p.OutputFile.Close()
		p.OutputFile = nil
	}
	p.cmd = nil
}
コード例 #4
0
ファイル: main.go プロジェクト: wangtuanjie/cfs
func main() {
	configfn := flag.String("config", "default.conf", "location of configuration file")
	flag.Parse()

	data, err := ioutil.ReadFile(*configfn)
	if err != nil {
		log.Fatalf("server: cannot load configuration file[%s] (%v)", *configfn, err)
	}

	var conf config.Server
	if _, err := toml.Decode(string(data), &conf); err != nil {
		log.Fatalf("server: configuration file[%s] is not valid (%v)", *configfn, err)
	}

	// default is that cfs is bootstrapped using docker
	cname, err := detectDockerContainer()
	if err != nil {
		log.Printf("server: failed to detect docker container (%v)", err)
	} else {
		stats.SetContainerName(cname)
		log.Printf("server: detect docker container %q", cname)
	}

	log.Infof("server: starting server...")

	lis, err := net.Listen("tcp", net.JoinHostPort(conf.Bind, conf.Port))
	if err != nil {
		log.Fatalf("server: failed to listen: %v", err)
	}

	log.Infof("server: listening on %s", net.JoinHostPort(conf.Bind, conf.Port))

	cfs := NewServer()

	for _, d := range conf.Disks {
		err = cfs.AddDisk(d.Name, d.Root)
		if err != nil {
			log.Fatalf("server: failed to add disk (%v)", err)
		}
	}

	// 0x1234 is the client ID for cfsctl, and its quota is 10 req/sec.
	enforce.SetQuota(0x1234, 10)

	// TODO report with influxSinker
	stats.Report(nil, 3*time.Second)

	s := grpc.NewServer()
	pb.RegisterCfsServer(s, cfs)
	pb.RegisterStatsServer(s, stats.Server())
	log.Infof("server: ready to serve clients")
	s.Serve(lis)
}
コード例 #5
0
ファイル: stats_command.go プロジェクト: missmayo/cfs
func handleStats(ctx context.Context, c *client.Client) error {
	info, err := c.ContainerInfo(ctx)
	if err != nil {
		log.Printf("ContainerInfo err (%v)", err)
	} else {
		log.Printf("Container Info: %+v", info)
	}
	ms, err := c.Metrics(ctx)
	if err != nil {
		log.Printf("Metrics err (%v)", err)
	} else {
		log.Printf("Metrics: %+v", ms)
	}
	return nil
}
コード例 #6
0
ファイル: keeper.go プロジェクト: anley/webcron
func (k *Keeper) ListUniqRecords() (rs []*Record, err error) {
	traveled := make(map[string]bool)
	rs = make([]*Record, 0)
	for _, rec := range k.runRecs {
		traveled[rec.Name] = true
		rs = append(rs, rec)
	}

	for _, task := range k.orderedTasks() {
		if traveled[task.Name] {
			continue
		}
		traveled[task.Name] = true
		var rec = new(Record)
		exists, err := xe.Where("`name` = ?", task.Name).Desc("created_at").Get(rec)
		if !exists || err != nil {
			log.Printf("exists: %v, err: %v", exists, err)
			rec.Name = task.Name
			rec.Status = STATUS_PENDING
			rec.T = task
		}
		rs = append(rs, rec)
	}
	return rs, nil
}
コード例 #7
0
ファイル: netpipe.go プロジェクト: yuancc/proxylocal
func (p *ProxyConn) pipe(src, dst net.Conn) chan error {
	//data direction
	errch := make(chan error, 1)
	islocal := src == p.lconn

	//directional copy (64k buffer)
	buff := make([]byte, 0xffff)
	go func() {
		for {
			n, err := src.Read(buff)
			if err != nil {
				errch <- err
				return
			}
			b := buff[:n]

			//write out result
			n, err = dst.Write(b)
			if err != nil {
				errch <- err
				log.Printf("Write failed '%s'\n", err)
				return
			}
			log.Debug("pipe --> local:", islocal, "write:", n) //, string(b[:n]))
			if islocal {
				p.sentBytes += uint64(n)
				p.stats.sentBytes += uint64(n)
			} else {
				p.receivedBytes += uint64(n)
				p.stats.receivedBytes += uint64(n)
			}
		}
	}()
	return errch
}
コード例 #8
0
ファイル: web.go プロジェクト: codeskyblue/gosuv
func (s *Supervisor) wsEvents(w http.ResponseWriter, r *http.Request) {
	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("upgrade:", err)
		return
	}
	defer c.Close()

	ch := make(chan string, 0)
	s.addStatusChangeListener(ch)
	go func() {
		_, _ = <-ch // ignore the history messages
		for message := range ch {
			// Question: type 1 ?
			c.WriteMessage(1, []byte(message))
		}
		// s.eventB.RemoveListener(ch)
	}()
	for {
		mt, message, err := c.ReadMessage()
		if err != nil {
			log.Println("read:", mt, err)
			break
		}
		log.Printf("recv: %v %s", mt, message)
		err = c.WriteMessage(mt, message)
		if err != nil {
			log.Println("write:", err)
			break
		}
	}
}
コード例 #9
0
ファイル: main.go プロジェクト: millken/ydaemon
func main() {
	flag.Parse()

	log.SetOutputLevel(*flagdebug)

	configFileName := filepath.Clean(*flagconfig + "/main.conf")
	log.Debugf("config file '%s'\n", configFileName)

	log.Printf("Starting %s\n", VERSION)

	if *cpuprofile != "" {
		prof, err := os.Create(*cpuprofile)
		if err != nil {
			panic(err.Error())
		}

		pprof.StartCPUProfile(prof)
		defer func() {
			log.Println("closing file")
			prof.Close()
		}()
		defer func() {
			log.Println("stopping profile")
			pprof.StopCPUProfile()
		}()
	}

	go configWatcher(configFileName)

	terminate := make(chan os.Signal)
	signal.Notify(terminate, os.Interrupt)

	<-terminate
	log.Printf("signal received, stopping")

	if *memprofile != "" {
		f, err := os.Create(*memprofile)
		if err != nil {
			log.Fatal(err)
		}
		pprof.WriteHeapProfile(f)
		f.Close()
	}

	//os.Exit(0)

}
コード例 #10
0
ファイル: web.go プロジェクト: codeskyblue/gosuv
func (s *Supervisor) AutoStartPrograms() {
	for _, proc := range s.procMap {
		if proc.Program.StartAuto {
			log.Printf("auto start %s", strconv.Quote(proc.Name))
			proc.Operate(StartEvent)
		}
	}
}
コード例 #11
0
ファイル: web.go プロジェクト: codeskyblue/gosuv
func (s *Supervisor) removeProgram(name string) {
	names := make([]string, 0, len(s.names))
	for _, pName := range s.names {
		if pName == name {
			continue
		}
		names = append(names, pName)
	}
	s.names = names
	log.Printf("stop before delete program: %s", name)
	s.stopAndWait(name)
	delete(s.procMap, name)
	delete(s.pgMap, name)
	s.broadcastEvent(name + " deleted")
}
コード例 #12
0
ファイル: web.go プロジェクト: codeskyblue/gosuv
func (s *Supervisor) catchExitSignal() {
	sigC := make(chan os.Signal, 1)
	signal.Notify(sigC, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP)
	go func() {
		for sig := range sigC {
			if sig == syscall.SIGHUP {
				log.Println("Receive SIGHUP, just ignore")
				continue
			}
			log.Printf("Got signal: %v, stopping all running process\n", sig)
			s.Close()
			break
		}
		os.Exit(0)
	}()
}
コード例 #13
0
ファイル: gosuv.go プロジェクト: codeskyblue/gosuv
func actionStartServer(c *cli.Context) error {
	suv, hdlr, err := newSupervisorHandler()
	if err != nil {
		log.Fatal(err)
	}
	auth := cfg.Server.HttpAuth
	if auth.Enabled {
		hdlr = httpauth.SimpleBasicAuth(auth.User, auth.Password)(hdlr)
	}
	http.Handle("/", hdlr)

	addr := cfg.Server.Addr
	if c.Bool("foreground") {
		suv.AutoStartPrograms()
		log.Printf("server listen on %v", addr)
		log.Fatal(http.ListenAndServe(addr, nil))
	} else {
		if checkServerStatus() == nil {
			fmt.Println("server is already running")
			return nil
		}
		logPath := filepath.Join(defaultConfigDir, "gosuv.log")
		logFd, err := os.OpenFile(logPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
		if err != nil {
			log.Fatalf("create file %s failed: %v", logPath, err)
		}
		cmd := exec.Command(os.Args[0], "start-server", "-f")
		cmd.Stdout = logFd
		cmd.Stderr = logFd
		err = cmd.Start()
		if err != nil {
			log.Fatal(err)
		}
		select {
		case err = <-GoFunc(cmd.Wait):
			log.Fatalf("server started failed, %v", err)
		case <-time.After(200 * time.Millisecond):
			showAddr := addr
			if strings.HasPrefix(addr, ":") {
				showAddr = "0.0.0.0" + addr
			}
			fmt.Printf("server started, listening on %s\n", showAddr)
		}
	}
	return nil
}
コード例 #14
0
ファイル: web.go プロジェクト: insionng/gosuv
func addHandler(w http.ResponseWriter, r *http.Request) {
	pinfo := new(ProgramInfo)
	err := json.NewDecoder(r.Body).Decode(pinfo)
	if err != nil {
		http.Error(w, err.Error(), 502)
		return
	}
	log.Printf("add: %#v", pinfo)

	program := NewProgram(pinfo)
	if err = programTable.AddProgram(program); err != nil {
		http.Error(w, err.Error(), 503)
		return
	}
	program.InputData(EVENT_START)

	renderJSON(w, &JSONResponse{
		Code:    200,
		Message: "program add success",
	})
}
コード例 #15
0
ファイル: web.go プロジェクト: anley/webcron
func main() {
	flag.StringVar(&gcfg.SchedFile, "sched", "sched.json", "file which store schedule setting")
	flag.IntVar(&gcfg.ServerPort, "port", 4000, "port to listen")
	flag.StringVar(&gcfg.LogDir, "logdir", "logs", "log directory")
	flag.Parse()

	var err error
	xe, err = xorm.NewEngine("sqlite3", "./test.db")
	//xe, err = xorm.NewEngine("mysql", "cron:cron@tcp(10.246.13.180:3306)/cron?charset=utf8")
	// xe, err = xorm.NewEngine("mysql", "root:@/cron?charset=utf8")
	if err != nil {
		log.Fatal(err)
	}
	if err := xe.Sync(Record{}); err != nil {
		log.Fatal(err)
	}

	if _, err = os.Stat(gcfg.LogDir); err != nil {
		os.Mkdir(gcfg.LogDir, 0755)
	}
	if _, err = os.Stat(gcfg.SchedFile); err != nil {
		ioutil.WriteFile(gcfg.SchedFile, []byte("[]"), 0644)
	}
	tasks, err := loadTasks(gcfg.SchedFile)
	if err != nil {
		log.Fatal(err)
	}
	log.Println(tasks)

	keeper = NewKeeper(tasks)

	initRoutes()
	log.Printf("Listening on *:%d", gcfg.ServerPort)
	http.Handle("/", m)
	//http.Handle("/-/", http.StripPrefix("/-/", http.FileServer(http.Dir("public"))))
	if err := http.ListenAndServe(":"+strconv.Itoa(gcfg.ServerPort), nil); err != nil {
		log.Fatal(err)
	}
}
コード例 #16
0
ファイル: parse.go プロジェクト: codeskyblue/shweb
func parseCfgFile(file string, m *macaron.Macaron) error {
	fd, err := os.Open(file)
	if err != nil {
		return err
	}
	defer fd.Close()

	rd := bufio.NewReader(fd)
	for {
		bline, _, err := rd.ReadLine() // Just ignore isPrefix(maybe not good)
		if err != nil {
			break
		}
		line := string(bline)
		if strings.HasPrefix(line, "#") {
			continue
		}
		fields, err := shellquote.Split(line)
		if err != nil {
			log.Printf("Shellquote parse error: %v", err)
			continue
		}
		if !(len(fields) >= 3 && len(fields) <= 4) {
			continue
		}

		method, patten, script := fields[0], fields[1], fields[2]
		contentType := ""
		if len(fields) == 4 {
			contentType = fields[3]
		} else {
		}
		addRoute(m, method, patten, script, contentType)
	}
	return nil
}