# Process Manager The Process Manager (`processmanager`) is a Go package responsible for starting, stopping, monitoring, and managing system processes. It provides a robust way to handle long-running tasks, scheduled jobs (via cron expressions), and general command execution with logging capabilities. It can be interacted with via `heroscript` commands, typically through a telnet interface to a `ProcessManagerHandler` server. ## Features - **Start and Stop Processes**: Launch new processes and terminate existing ones. - **Restart Processes**: Convenience function to stop, delete, and restart a process. - **Delete Processes**: Remove a process definition and its associated logs. - **Process Monitoring**: Tracks process status (running, stopped, failed, completed), PID, CPU, and memory usage. - **Logging**: Captures stdout and stderr for each managed process. Logs are stored in a configurable base directory, with each process having its own subdirectory. - **Deadline Management**: Processes can be started with a deadline, after which they will be automatically stopped. - **Cron Scheduling**: Processes can be scheduled to run based on cron expressions (though the actual scheduling logic might be external and trigger `process.start`). - **Heroscript Integration**: Exposes functionality through `heroscript` actions. ## Direct Usage in Go (Conceptual) While primarily designed for `heroscript` interaction, the core `ProcessManager` can be used directly in Go applications: ```go package main import ( "fmt" "time" "git.ourworld.tf/herocode/heroagent/pkg/system/processmanager" ) func main() { pm := processmanager.NewProcessManager() // Configure logs path (optional, defaults to a temp directory) // pm.SetLogsBasePath("./my_process_logs") processName := "my_go_task" command := "sleep 10 && echo 'Task finished'" fmt.Printf("Starting process: %s\n", processName) err := pm.StartProcess(processName, command, true, 0, "", "") // name, command, logEnabled, deadline, cron, jobID if err != nil { fmt.Printf("Error starting process: %v\n", err) return } fmt.Printf("Process '%s' started. Waiting for it to complete or monitoring...\n", processName) // Monitor status (example) for i := 0; i < 12; i++ { time.Sleep(1 * time.Second) status, err := pm.GetProcessStatus(processName) if err != nil { fmt.Printf("Error getting status: %v\n", err) break } fmt.Printf("Status of '%s': %s (PID: %d, CPU: %.2f%%, Mem: %.2fMB)\n", status.Name, status.Status, status.PID, status.CPUPercent, status.MemoryMB) if status.Status == processmanager.ProcessStatusCompleted || status.Status == processmanager.ProcessStatusFailed { fmt.Printf("Process '%s' ended with status: %s\n", processName, status.Status) if status.Error != "" { fmt.Printf("Error: %s\n", status.Error) } break } } // Retrieve logs logs, err := pm.GetProcessLogs(processName, 100) if err != nil { fmt.Printf("Error getting logs: %v\n", err) } else { fmt.Printf("\n--- Logs for %s ---\n%s\n-------------------\n", processName, logs) } // Stop (if still running) and delete fmt.Printf("Stopping process: %s\n", processName) pm.StopProcess(processName) // Ignoring error for simplicity if already stopped fmt.Printf("Deleting process: %s\n", processName) err = pm.DeleteProcess(processName) if err != nil { fmt.Printf("Error deleting process: %v\n", err) } fmt.Println("Done.") } ```