summaryrefslogtreecommitdiff
path: root/run.go
diff options
context:
space:
mode:
authorJeff Carr <[email protected]>2025-10-07 04:55:46 -0500
committerJeff Carr <[email protected]>2025-10-07 04:55:46 -0500
commit46d67313cff2fc06975a53059f38555bc04d820e (patch)
tree925d128416c8d7779acb831465053b6b757e0b2e /run.go
parent8c15048135fbf64592aa9fe31466ed09d520d2b0 (diff)
add sudo but it doesn't work and isn't rightv0.0.29
Diffstat (limited to 'run.go')
-rw-r--r--run.go101
1 files changed, 101 insertions, 0 deletions
diff --git a/run.go b/run.go
new file mode 100644
index 0000000..5fbeb7c
--- /dev/null
+++ b/run.go
@@ -0,0 +1,101 @@
+package fhelp
+
+import (
+ "errors"
+ "time"
+
+ "github.com/go-cmd/cmd"
+ "go.wit.com/log"
+)
+
+func RunRealtime(args []string) cmd.Status {
+ return PathRunRealtime("", args)
+}
+
+// this is stuff from a long time ago that there must be a replacement for
+func RemoveFirstElement(slice []string) (string, []string) {
+ if len(slice) == 0 {
+ return "", slice // Return the original slice if it's empty
+ }
+ return slice[0], slice[1:] // Return the slice without the first element
+}
+
+// echos twice a second if anything sends to STDOUT or STDERR
+// not great, but it's really just for watching things run in real time anyway
+// TODO: fix \r handling for things like git-clone so the terminal doesn't
+// have to do a \n newline each time.
+// TODO: add timeouts and status of things hanging around forever
+func PathRunRealtime(pwd string, args []string) cmd.Status {
+ // Check if the slice has at least one element (the command name)
+ if len(args) == 0 {
+ var s cmd.Status
+ s.Error = errors.New("Error: Command slice is empty.")
+ return s
+ }
+
+ // Start a long-running process, capture stdout and stderr
+ a, b := RemoveFirstElement(args)
+ findCmd := cmd.NewCmd(a, b...)
+ if pwd != "" {
+ findCmd.Dir = pwd
+ }
+ statusChan := findCmd.Start() // non-blocking
+
+ ticker := time.NewTicker(100 * time.Microsecond)
+
+ // this is interesting, maybe useful, but wierd, but neat. interesting even
+ // Print last line of stdout every 2s
+ go func() {
+ // loop very quickly, but only print the line if it changes
+ var lastout string
+ var lasterr string
+ for range ticker.C {
+ status := findCmd.Status()
+ n := len(status.Stdout)
+ if n != 0 {
+ newline := status.Stdout[n-1]
+ if lastout != newline {
+ lastout = newline
+ log.Info(lastout)
+ }
+ }
+ n = len(status.Stderr)
+ if n != 0 {
+ newline := status.Stderr[n-1]
+ if lasterr != newline {
+ lasterr = newline
+ log.Info(lasterr)
+ }
+ }
+ if status.Complete {
+ return
+ }
+ }
+ }()
+
+ // Stop command after 1 hour
+ go func() {
+ <-time.After(1 * time.Hour)
+ findCmd.Stop()
+ }()
+
+ // Check if command is done
+ select {
+ case finalStatus := <-statusChan:
+ log.Info("finalStatus =", finalStatus.Exit, finalStatus.Error)
+ return finalStatus
+ // done
+ default:
+ // no, still running
+ }
+
+ // Block waiting for command to exit, be stopped, or be killed
+ // there are things being left around here. debug this
+ finalStatus := <-statusChan
+ if len(finalStatus.Cmd) != 0 {
+ if string(finalStatus.Cmd) != "go" {
+ log.Info("shell.Run() ok goroutine end?", finalStatus.Cmd, finalStatus.Exit)
+ }
+ }
+ return findCmd.Status()
+}