Compare commits
No commits in common. "master" and "v0.22.16" have entirely different histories.
51
cmd.go
51
cmd.go
|
@ -2,7 +2,6 @@ package shell
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"os"
|
"os"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -176,7 +175,7 @@ func PathRunRealtime(pwd string, args []string) cmd.Status {
|
||||||
}
|
}
|
||||||
statusChan := findCmd.Start() // non-blocking
|
statusChan := findCmd.Start() // non-blocking
|
||||||
|
|
||||||
ticker := time.NewTicker(100 * time.Microsecond)
|
ticker := time.NewTicker(5 * time.Millisecond)
|
||||||
|
|
||||||
// this is interesting, maybe useful, but wierd, but neat. interesting even
|
// this is interesting, maybe useful, but wierd, but neat. interesting even
|
||||||
// Print last line of stdout every 2s
|
// Print last line of stdout every 2s
|
||||||
|
@ -229,7 +228,7 @@ func PathRunRealtime(pwd string, args []string) cmd.Status {
|
||||||
finalStatus := <-statusChan
|
finalStatus := <-statusChan
|
||||||
if len(finalStatus.Cmd) != 0 {
|
if len(finalStatus.Cmd) != 0 {
|
||||||
if string(finalStatus.Cmd) != "go" {
|
if string(finalStatus.Cmd) != "go" {
|
||||||
log.Info("shell.Run() ok goroutine end?", finalStatus.Cmd, finalStatus.Exit)
|
log.Info("shell.Run() finalStatus.Cmd is", finalStatus.Cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return findCmd.Status()
|
return findCmd.Status()
|
||||||
|
@ -242,49 +241,3 @@ func RemoveFirstElement(slice []string) (string, []string) {
|
||||||
}
|
}
|
||||||
return slice[0], slice[1:] // Return the slice without the first element
|
return slice[0], slice[1:] // Return the slice without the first element
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunVerbose(cmd []string) (*cmd.Status, error) {
|
|
||||||
pwd, _ := os.Getwd()
|
|
||||||
log.Info("Running:", pwd, cmd)
|
|
||||||
r, err := RunStrict(cmd)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("Error", cmd, err)
|
|
||||||
}
|
|
||||||
for _, line := range r.Stdout {
|
|
||||||
log.Info(line)
|
|
||||||
}
|
|
||||||
for _, line := range r.Stderr {
|
|
||||||
log.Info(line)
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func RunVerboseOnError(cmd []string) (*cmd.Status, error) {
|
|
||||||
r, err := RunStrict(cmd)
|
|
||||||
if err == nil {
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
pwd, _ := os.Getwd()
|
|
||||||
log.Info("Run Error:", pwd, cmd, err)
|
|
||||||
for _, line := range r.Stdout {
|
|
||||||
log.Info(line)
|
|
||||||
}
|
|
||||||
for _, line := range r.Stderr {
|
|
||||||
log.Info(line)
|
|
||||||
}
|
|
||||||
return r, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func RunStrict(cmd []string) (*cmd.Status, error) {
|
|
||||||
pwd, _ := os.Getwd()
|
|
||||||
result := PathRunQuiet(pwd, cmd)
|
|
||||||
if result.Error != nil {
|
|
||||||
log.Warn(pwd, cmd, "wow. golang is cool. an os.Error:", result.Error)
|
|
||||||
return &result, result.Error
|
|
||||||
}
|
|
||||||
if result.Exit != 0 {
|
|
||||||
// log.Warn(cmd, "failed with", result.Exit, repo.GetGoPath())
|
|
||||||
return &result, errors.New(fmt.Sprint(cmd, "failed with", result.Exit))
|
|
||||||
}
|
|
||||||
return &result, nil
|
|
||||||
}
|
|
||||||
|
|
71
exec.go
71
exec.go
|
@ -1,71 +0,0 @@
|
||||||
package shell
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
|
|
||||||
"go.wit.com/log"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Exec(args []string) error {
|
|
||||||
if len(args) == 0 {
|
|
||||||
return errors.New("Error: Command slice is empty.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start a long-running process, capture stdout and stderr
|
|
||||||
a, b := RemoveFirstElement(args)
|
|
||||||
|
|
||||||
process := exec.Command(a, b...)
|
|
||||||
process.Stderr = os.Stderr
|
|
||||||
process.Stdin = os.Stdin
|
|
||||||
process.Stdout = os.Stdout
|
|
||||||
process.Start()
|
|
||||||
err := process.Wait()
|
|
||||||
log.Log(INFO, "shell.Exec() err =", err)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ExecCheck(args []string) error {
|
|
||||||
if len(args) == 0 {
|
|
||||||
return errors.New("Error: Command slice is empty.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start a long-running process, capture stdout and stderr
|
|
||||||
a, b := RemoveFirstElement(args)
|
|
||||||
|
|
||||||
process := exec.Command(a, b...)
|
|
||||||
process.Stderr = os.Stderr
|
|
||||||
process.Stdin = os.Stdin
|
|
||||||
process.Stdout = os.Stdout
|
|
||||||
err := process.Run()
|
|
||||||
if err != nil {
|
|
||||||
log.Info("ExecCheck() err", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// log.Info("ExecCheck() nil")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func PathExecVerbose(path string, args []string) error {
|
|
||||||
if len(args) == 0 {
|
|
||||||
return errors.New("Error: Command slice is empty.")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start a long-running process, capture stdout and stderr
|
|
||||||
a, b := RemoveFirstElement(args)
|
|
||||||
|
|
||||||
process := exec.Command(a, b...)
|
|
||||||
process.Dir = path
|
|
||||||
process.Stderr = os.Stderr
|
|
||||||
process.Stdin = os.Stdin
|
|
||||||
process.Stdout = os.Stdout
|
|
||||||
err := process.Run()
|
|
||||||
log.Info("Exec() cmd:", args)
|
|
||||||
if err != nil {
|
|
||||||
log.Info("ExecCheck() err", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// log.Info("ExecCheck() nil")
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
package shell
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func SudoRaw(c []string) {
|
|
||||||
args := []string{"-S"}
|
|
||||||
args = append(args, c...)
|
|
||||||
cmd := exec.Command("sudo", args...)
|
|
||||||
|
|
||||||
// Assign the current process's standard input, output, and error
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stdin = os.Stdin
|
|
||||||
|
|
||||||
// Ensure the process has a terminal session
|
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
||||||
Setsid: true, // Start a new session
|
|
||||||
}
|
|
||||||
|
|
||||||
err := cmd.Run()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Command execution failed:", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Sudo(c []string) error {
|
|
||||||
args := []string{"-S"}
|
|
||||||
// args := []string{}
|
|
||||||
args = append(args, c...)
|
|
||||||
cmd := exec.Command("sudo", args...)
|
|
||||||
|
|
||||||
// Open the terminal device directly to preserve input/output control
|
|
||||||
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Failed to open /dev/tty:", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer tty.Close()
|
|
||||||
|
|
||||||
// Assign the TTY explicitly
|
|
||||||
cmd.Stdin = tty
|
|
||||||
cmd.Stdout = tty
|
|
||||||
cmd.Stderr = tty
|
|
||||||
|
|
||||||
// Ensure the new process gets its own session
|
|
||||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
|
||||||
Setsid: true, // Start a new session
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the command
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
fmt.Println("Command execution failed:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("\nProcess finished. TTY restored.")
|
|
||||||
return nil
|
|
||||||
}
|
|
|
@ -3,6 +3,8 @@ package shell
|
||||||
// old code and probably junk
|
// old code and probably junk
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
|
@ -14,11 +16,11 @@ import (
|
||||||
|
|
||||||
var callback func(interface{}, int)
|
var callback func(interface{}, int)
|
||||||
|
|
||||||
// var shellStdout *os.File
|
var shellStdout *os.File
|
||||||
// var shellStderr *os.File
|
var shellStderr *os.File
|
||||||
|
|
||||||
// var spewOn bool = false
|
var spewOn bool = false
|
||||||
// var quiet bool = false
|
var quiet bool = false
|
||||||
|
|
||||||
// var msecDelay int = 20 // number of milliseconds to delay between reads with no data
|
// var msecDelay int = 20 // number of milliseconds to delay between reads with no data
|
||||||
|
|
||||||
|
@ -40,6 +42,26 @@ func InitCallback(f func(interface{}, int)) {
|
||||||
callback = f
|
callback = f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this means it won't copy all the output to STDOUT
|
||||||
|
func Quiet(q bool) {
|
||||||
|
quiet = q
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func Script(cmds string) int {
|
||||||
|
// split on new lines (while we are at it, handle stupid windows text files
|
||||||
|
lines := strings.Split(strings.Replace(cmds, "\r\n", "\n", -1), "\n")
|
||||||
|
|
||||||
|
for _, line := range lines {
|
||||||
|
line = Chomp(line) // this is like 'chomp' in perl
|
||||||
|
log.Log(INFO, "LINE:", line)
|
||||||
|
time.Sleep(1)
|
||||||
|
RunString(line)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
func Unlink(filename string) bool {
|
func Unlink(filename string) bool {
|
||||||
if err := os.Remove(filename); err != nil {
|
if err := os.Remove(filename); err != nil {
|
||||||
return Exists(filename)
|
return Exists(filename)
|
||||||
|
@ -85,11 +107,66 @@ func Exists(filename string) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// return true if the filename exists (cross-platform)
|
// makes the directory
|
||||||
|
func Mkdir(dir string) bool {
|
||||||
|
if Dir(dir) {
|
||||||
|
// already a dir
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if Exists(dir) {
|
||||||
|
// something else is there
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
Run([]string{"mkdir", "-p", dir})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func IsDir(dirname string) bool {
|
func IsDir(dirname string) bool {
|
||||||
|
return Dir(dirname)
|
||||||
|
}
|
||||||
|
|
||||||
|
// return true if the filename exists (cross-platform)
|
||||||
|
func Dir(dirname string) bool {
|
||||||
info, err := os.Stat(Path(dirname))
|
info, err := os.Stat(Path(dirname))
|
||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return info.IsDir()
|
return info.IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cat a file into a string
|
||||||
|
func Cat(filename string) string {
|
||||||
|
buffer, err := ioutil.ReadFile(Path(filename))
|
||||||
|
// log.Log(INFO, "buffer =", string(buffer))
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return string(buffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunPathHttpOut(path string, cmd []string, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
log.Warn("Run(): ", cmd)
|
||||||
|
|
||||||
|
process := exec.Command(cmd[0], cmd[1:len(cmd)]...)
|
||||||
|
process.Dir = path
|
||||||
|
process.Stderr = os.Stderr
|
||||||
|
process.Stdin = r.Body
|
||||||
|
process.Stdout = w
|
||||||
|
process.Start()
|
||||||
|
err := process.Wait()
|
||||||
|
log.Warn("shell.Exec() err =", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func RunHttpOut(cmd []string, w http.ResponseWriter, r *http.Request) error {
|
||||||
|
log.Warn("NewRun() ", cmd)
|
||||||
|
|
||||||
|
process := exec.Command(cmd[0], cmd[1:len(cmd)]...)
|
||||||
|
process.Stderr = os.Stderr
|
||||||
|
process.Stdin = r.Body
|
||||||
|
process.Stdout = w
|
||||||
|
process.Start()
|
||||||
|
err := process.Wait()
|
||||||
|
log.Warn("shell.Exec() err =", err)
|
||||||
|
return err
|
||||||
|
}
|
|
@ -1,17 +0,0 @@
|
||||||
package shell
|
|
||||||
|
|
||||||
import "regexp"
|
|
||||||
|
|
||||||
// splits strings. should work all the time
|
|
||||||
// A string with mixed line endings, including old Mac style (\r)
|
|
||||||
func SplitNewLines(input string) []string {
|
|
||||||
// This regex matches a carriage return and optional newline, OR just a newline.
|
|
||||||
// This covers \r\n, \n, and \r.
|
|
||||||
re := regexp.MustCompile(`\r\n?|\n|\r`)
|
|
||||||
|
|
||||||
// The -1 means there is no limit to the number of splits.
|
|
||||||
lines := re.Split(input, -1)
|
|
||||||
|
|
||||||
// Output: ["line one" "line two" "line three" "line four"]
|
|
||||||
return lines
|
|
||||||
}
|
|
|
@ -1,6 +1,12 @@
|
||||||
package shell
|
package shell
|
||||||
|
|
||||||
/*
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"os/exec"
|
||||||
|
)
|
||||||
|
|
||||||
var FileMap map[string]*File
|
var FileMap map[string]*File
|
||||||
|
|
||||||
var readBufferSize int
|
var readBufferSize int
|
||||||
|
@ -48,4 +54,3 @@ func New() *OldShell {
|
||||||
|
|
||||||
return &tmp
|
return &tmp
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
23
time.go
23
time.go
|
@ -51,14 +51,6 @@ func GetDurationStamp(t time.Time) string {
|
||||||
return FormatDuration(duration)
|
return FormatDuration(duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
// allows nil
|
|
||||||
func HumanDuration(d *time.Duration) string {
|
|
||||||
if d == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return FormatDuration(*d)
|
|
||||||
}
|
|
||||||
|
|
||||||
func FormatDuration(d time.Duration) string {
|
func FormatDuration(d time.Duration) string {
|
||||||
result := ""
|
result := ""
|
||||||
|
|
||||||
|
@ -102,19 +94,6 @@ func FormatDuration(d time.Duration) string {
|
||||||
if ms > 100 {
|
if ms > 100 {
|
||||||
// todo: print .3s, etc ?
|
// todo: print .3s, etc ?
|
||||||
}
|
}
|
||||||
if ms > 0 {
|
result += fmt.Sprintf("%dms", ms)
|
||||||
result += fmt.Sprintf("%dms", ms)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// report in milliseconds
|
|
||||||
mc := int(d.Microseconds())
|
|
||||||
if mc > 0 {
|
|
||||||
result += fmt.Sprintf("%dmc", mc)
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
ns := int(d.Nanoseconds())
|
|
||||||
result += fmt.Sprintf("%dns", ns)
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
2
wget.go
2
wget.go
|
@ -34,7 +34,7 @@ func Wget(url string) *bytes.Buffer {
|
||||||
|
|
||||||
log.Log(INFO, "res.StatusCode: %d\n", resp.StatusCode)
|
log.Log(INFO, "res.StatusCode: %d\n", resp.StatusCode)
|
||||||
if resp.StatusCode != 200 {
|
if resp.StatusCode != 200 {
|
||||||
handleError(fmt.Errorf("%d", resp.StatusCode), -1)
|
handleError(fmt.Errorf(fmt.Sprintf("%d", resp.StatusCode)), -1)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
9
xterm.go
9
xterm.go
|
@ -3,6 +3,7 @@ package shell
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
)
|
)
|
||||||
|
@ -126,17 +127,16 @@ func XtermCmd(path string, cmd []string) {
|
||||||
// runs an xterm
|
// runs an xterm
|
||||||
// waits until xterm exits
|
// waits until xterm exits
|
||||||
func XtermCmdWait(path string, cmd []string) {
|
func XtermCmdWait(path string, cmd []string) {
|
||||||
// var argsXterm = getXtermCmd(cmd)
|
var argsXterm = getXtermCmd(cmd)
|
||||||
|
|
||||||
log.Info("XtermCmd() path =", path, "cmd =", cmd)
|
log.Info("XtermCmd() path =", path, "cmd =", argsXterm)
|
||||||
|
|
||||||
// keeps git diff from exiting on small diffs
|
// keeps git diff from exiting on small diffs
|
||||||
os.Setenv("LESS", "-+F -+X -R")
|
os.Setenv("LESS", "-+F -+X -R")
|
||||||
|
|
||||||
PathRunLog(path, cmd, INFO)
|
PathRunLog(path, argsXterm, INFO)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
// spawns an xterm with something you can run at a command line
|
// spawns an xterm with something you can run at a command line
|
||||||
// then executes bash
|
// then executes bash
|
||||||
func XtermCmdBash(path string, cmd []string) {
|
func XtermCmdBash(path string, cmd []string) {
|
||||||
|
@ -149,4 +149,3 @@ func XtermCmdBash(path string, cmd []string) {
|
||||||
log.Info("XtermCmd() path =", path, "cmd =", tmp)
|
log.Info("XtermCmd() path =", path, "cmd =", tmp)
|
||||||
go PathRunLog(path, tmp, INFO)
|
go PathRunLog(path, tmp, INFO)
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
Loading…
Reference in New Issue