mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2026-04-15 01:41:56 +00:00
71 lines
1.3 KiB
Go
71 lines
1.3 KiB
Go
package utils
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"time"
|
|
)
|
|
|
|
type Service struct {
|
|
cmd *exec.Cmd
|
|
env map[string]string
|
|
}
|
|
|
|
func NewService(cmdName string, args ...string) *Service {
|
|
cmd := exec.Command(cmdName, args...)
|
|
return &Service{
|
|
cmd: cmd,
|
|
env: make(map[string]string),
|
|
}
|
|
}
|
|
|
|
func (s *Service) Start() error {
|
|
// Inherit parent environment
|
|
env := os.Environ()
|
|
for key, value := range s.env {
|
|
env = append(env, fmt.Sprintf("%s=%s", key, value))
|
|
}
|
|
s.cmd.Env = env
|
|
// Capture output for debugging
|
|
s.cmd.Stdout = os.Stdout
|
|
s.cmd.Stderr = os.Stderr
|
|
return s.cmd.Start()
|
|
}
|
|
|
|
func (s *Service) Stop() error {
|
|
if s.cmd == nil || s.cmd.Process == nil {
|
|
return fmt.Errorf("process not found / running")
|
|
}
|
|
|
|
// Try graceful shutdown first
|
|
if err := s.cmd.Process.Signal(os.Interrupt); err != nil {
|
|
// If interrupt fails, force kill
|
|
return s.cmd.Process.Kill()
|
|
}
|
|
|
|
// Wait for graceful shutdown with timeout
|
|
done := make(chan error, 1)
|
|
go func() {
|
|
done <- s.cmd.Wait()
|
|
}()
|
|
|
|
select {
|
|
case <-time.After(5 * time.Second):
|
|
// Force kill after timeout
|
|
return s.cmd.Process.Kill()
|
|
case err := <-done:
|
|
return err
|
|
}
|
|
}
|
|
|
|
func (s *Service) SetEnv(key, value string) *Service {
|
|
s.env[key] = value
|
|
return s
|
|
}
|
|
|
|
func (s *Service) WorkDir(workDir string) *Service {
|
|
s.cmd.Dir = workDir
|
|
return s
|
|
}
|