gorun

package module
v0.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 15, 2025 License: MIT Imports: 11 Imported by: 0

README

gorun

Project Badges

gorun is a Go package that provides a simple interface to run, monitor, and stop external programs, capturing their output and handling graceful shutdowns.

Usage

Installation
go get github.com/cdvelop/gorun
Example
package main

import (
    "os"
    "github.com/cdvelop/gorun"
)

func main() {
    config := &gorun.Config{
        ExecProgramPath: "your_program",
        RunArguments:    func() []string { return []string{"--flag"} },
        ExitChan:        make(chan bool),
        Logger:          os.Stdout,
    }

    runner := gorun.New(config)

    // Start the program
    if err := runner.RunProgram(); err != nil {
        panic(err)
    }

    // ... do other work ...

    // Stop the program gracefully
    if err := runner.StopProgram(); err != nil {
        panic(err)
    }
}
API
type Config

Configuration for running an external program.

  • ExecProgramPath string: Path to the executable.
  • RunArguments func() []string: Function returning the arguments to pass.
  • ExitChan chan bool: Channel to signal exit.
  • Logger io.Writer: Where to write program output.
  • KillAllOnStop bool: If true, kills all instances of the executable when stopping.
  • WorkingDir string: Optional working directory to set for the spawned process. Useful when the executable expects to run from a specific folder (for example a web server that serves ./public). If empty, the process inherits the parent's working directory.
func New(config *Config) *GoRun

Creates a new runner instance.

func (g *GoRun) RunProgram() error

Runs the configured program and captures its output. If a program is already running, it stops the previous one first. If KillAllOnStop is enabled, it will also kill all other instances of the same executable.

func (g *GoRun) StopProgram() error

Stops the running program gracefully. If KillAllOnStop is enabled, it will also kill all other instances of the same executable.

func (g *GoRun) StopProgramAndCleanup(killAll bool) error

Stops the running program and optionally kills all instances of the same executable by name.

func KillAllByName(executableName string) error

Kills all running processes that match the given executable name. This is useful for cleanup when multiple instances might be running. Works cross-platform (Linux, Windows, macOS).

func (g *GoRun) GetOutput() string

Returns the captured output (stdout + stderr) from the running process in a thread-safe way. Useful for tests and debugging.

New Cleanup Features

Starting from this version, gorun includes enhanced cleanup capabilities to handle scenarios where multiple instances of the same program might be running:

Automatic Cleanup

Set KillAllOnStop: true in your config to automatically kill all instances:

config := &gorun.Config{
    ExecProgramPath: "./my-server",
    RunArguments:    func() []string { return []string{"--port", "8080"} },
    ExitChan:        make(chan bool),
    Logger:          os.Stdout,
    KillAllOnStop:   true, // Kill ALL instances when stopping
}
Manual Cleanup

For explicit control over cleanup:

// Kill all instances manually
if err := gorun.KillAllByName("my-server"); err != nil {
    log.Printf("Cleanup failed: %v", err)
}

// Or use the method with explicit control
if err := runner.StopProgramAndCleanup(true); err != nil {
    log.Printf("Stop and cleanup failed: %v", err)
}
Use Cases

This is particularly useful for:

  • Development servers: Ensure no orphaned processes when restarting
  • Test cleanup: Prevent test pollution from previous runs
  • CI/CD: Ensure clean deployment environments
  • Multiple instances: When you need to ensure only one instance runs

For more details, see the GoDoc or the source

WorkingDir notes

Some programs rely on relative paths (for example web servers that serve ./public). Use the WorkingDir field in Config to ensure the spawned process runs with the expected current directory. Example:

config := &gorun.Config{
    ExecProgramPath: "./my-server",
    WorkingDir:      "/home/user/project/pwa",
    ExitChan:        make(chan bool),
    Logger:          os.Stdout,
}

runner := gorun.New(config)
_ = runner.RunProgram()

Testing

Run the gorun tests locally with:

cd gorun
go test ./... -v

Or run a single test (example):

cd gorun
go test -run TestWorkingDir -v

These tests exercise WorkingDir handling and cleanup behaviors.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func KillAllByName added in v0.0.4

func KillAllByName(executableName string) error

KillAllByName kills all running processes that match the given executable name This is useful for cleanup when multiple instances might be running

Types

type Config added in v0.0.7

type Config struct {
	ExecProgramPath string // eg: "server/main.exe"
	RunArguments    func() []string
	ExitChan        chan bool
	Logger          io.Writer
	KillAllOnStop   bool   // If true, kills all instances of the executable when stopping
	WorkingDir      string // Working directory for the process (optional)
}

type GoRun

type GoRun struct {
	*Config
	Cmd *exec.Cmd
	// contains filtered or unexported fields
}

func New

func New(c *Config) *GoRun

func (*GoRun) GetOutput added in v0.0.5

func (h *GoRun) GetOutput() string

GetOutput returns the captured output in a thread-safe manner

func (*GoRun) GetPID added in v0.0.4

func (h *GoRun) GetPID() int

GetPID returns the process ID if the program is running, otherwise returns 0

func (*GoRun) IsRunning

func (h *GoRun) IsRunning() bool

IsRunning returns whether the program is currently running

func (*GoRun) RunProgram

func (h *GoRun) RunProgram() error

func (*GoRun) StopProgram

func (h *GoRun) StopProgram() error

func (*GoRun) StopProgramAndCleanup added in v0.0.4

func (h *GoRun) StopProgramAndCleanup(killAll bool) error

StopProgramAndCleanup stops the current program and optionally kills all instances of the same executable name

type SafeBuffer added in v0.0.5

type SafeBuffer struct {
	// contains filtered or unexported fields
}

SafeBuffer provides thread-safe operations on a bytes.Buffer and optionally forwards writes to another writer

func NewSafeBuffer added in v0.0.5

func NewSafeBuffer() *SafeBuffer

NewSafeBuffer creates a new thread-safe buffer

func NewSafeBufferWithForward added in v0.0.5

func NewSafeBufferWithForward(forward io.Writer) *SafeBuffer

NewSafeBufferWithForward creates a new thread-safe buffer that forwards writes

func (*SafeBuffer) Len added in v0.0.5

func (sb *SafeBuffer) Len() int

Len returns the length of the buffer in a thread-safe manner

func (*SafeBuffer) Reset added in v0.0.5

func (sb *SafeBuffer) Reset()

Reset resets the buffer in a thread-safe manner

func (*SafeBuffer) String added in v0.0.5

func (sb *SafeBuffer) String() string

String returns the contents of the buffer as a string in a thread-safe manner

func (*SafeBuffer) Write added in v0.0.5

func (sb *SafeBuffer) Write(p []byte) (n int, err error)

Write writes data to the buffer and optionally forwards to another writer

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL