Now can reliably run multiple processes and kill them externall at will.

master
Zed A. Shaw 2 days ago
parent fe091250bd
commit 8a0f8ece61
  1. 8
      .ozai.json
  2. 8
      config/settings.go
  3. 73
      main.go
  4. 12
      tools/cmd/tester/main.go

@ -1,14 +1,14 @@
{
"Processes": {
"tester1": {
"Name": "tester",
"Name": "tester1",
"Command": "tester",
"Args": ["-count", "10", "-id", "1"]
"Args": ["-count", "100", "-id", "1"]
},
"tester2": {
"Name": "tester",
"Name": "tester2",
"Command": "tester",
"Args": ["-count", "5", "-id", "2"]
"Args": ["-count", "500", "-id", "2"]
}
}
}

@ -5,16 +5,20 @@ import (
"log"
"os"
"io"
"os/exec"
"encoding/json"
)
type command struct {
type Process struct {
Command string
Args []string
Name string
Ready chan string
ExecCmd *exec.Cmd
}
type config struct {
Processes map[string]command
Processes map[string]Process
ConfigPath string
}

@ -6,6 +6,7 @@ import (
"log"
"io"
"time"
"math/rand"
"os"
"errors"
"sync"
@ -16,12 +17,39 @@ func LaunchLogger(in io.Reader, out io.Writer, err error) {
if err != nil { log.Fatal(err) }
go func() {
if _, err := io.Copy(out, in); err != nil {
log.Fatal(err)
}
if _, err := io.Copy(out, in)
err != nil { log.Printf("LOGGER: %v", err) }
}()
}
func LaunchProcess(proc *config.Process, wg sync.WaitGroup) {
defer wg.Done()
for {
proc.ExecCmd = exec.Command(proc.Command, proc.Args...)
if errors.Is(proc.ExecCmd.Err, exec.ErrDot) {
proc.ExecCmd.Err = nil
}
fmt.Println("STARTING", proc.Name)
stderr, err := proc.ExecCmd.StderrPipe();
LaunchLogger(stderr, os.Stdout, err)
stdout, err := proc.ExecCmd.StdoutPipe();
LaunchLogger(stdout, os.Stdout, err)
proc.ExecCmd.Start()
fmt.Println("WAITING for", proc.Name)
fmt.Println("SENDING READY on channel")
proc.Ready<- "ready"
proc.ExecCmd.Wait()
fmt.Println("PROCESS", proc.Name, "EXITED")
}
}
func main() {
config.Load()
@ -33,34 +61,21 @@ func main() {
fmt.Println("PROCESS:", name)
wg.Add(1)
go func() {
defer wg.Done()
proc.Ready = make(chan string)
go LaunchProcess(&proc, wg)
go func() {
for {
fmt.Println("STARTING", name)
cmd := exec.Command(proc.Command, proc.Args...)
if errors.Is(cmd.Err, exec.ErrDot) {
cmd.Err = nil
}
stderr, err := cmd.StderrPipe();
LaunchLogger(stderr, os.Stdout, err)
stdout, err := cmd.StdoutPipe();
LaunchLogger(stdout, os.Stdout, err)
cmd.Run()
fmt.Println("WAITING for", name)
go func() {
fmt.Println("killer runs")
time.Sleep(4 * time.Second)
fmt.Println("!!!!!!!!!!!!!!!!!!! TIME TO DIE!!!!!")
cmd.Process.Signal(os.Interrupt)
}()
cmd.Wait()
fmt.Println("PROC", name, "EXITED SEND QUIT")
fmt.Println("!!!!!!!!!!!!!!!!!!!!!!!!!! killer runs")
is_ready := <-proc.Ready
fmt.Println("is_ready returned", is_ready)
sleep_for := rand.Int() % 10 + 1
time.Sleep(time.Duration(sleep_for) * time.Second)
fmt.Println("!!!!!!!!!!!!!!!!!!! TIME TO DIE!!!!!")
err := proc.ExecCmd.Process.Kill()
if err != nil { log.Printf("killer says: %v", err) }
}
}()
}

@ -7,11 +7,12 @@ import (
"sync"
)
func Worker(name string, done chan<- int, stop <-chan int) {
for i := 0; i < 10; i++ {
func Worker(name string, count int, done chan<- int, stop <-chan int) {
for i := 0; i < count; i++ {
select {
case <-stop:
fmt.Println("Worker stopped:", name)
done<- 1
return
default:
time.Sleep(1 * time.Second)
@ -26,15 +27,14 @@ func Supervisor(id int, count int) {
stop := make(chan int)
var wg sync.WaitGroup
for i := 0; i < count; i++ {
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for {
workerDone := make(chan int)
go Worker(fmt.Sprintf("%d:%d", id, i), workerDone, stop)
go Worker(fmt.Sprintf("%d:%d", id, i), count, workerDone, stop)
select {
case <-workerDone:
@ -48,11 +48,13 @@ func Supervisor(id int, count int) {
}()
}
/*
go func() {
// test shutdown
time.Sleep(10000 * time.Millisecond)
close(stop)
}()
*/
wg.Wait()
}

Loading…
Cancel
Save