Skip to content

Instantly share code, notes, and snippets.

@taoky
Last active November 30, 2020 04:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save taoky/db7d1dab5b14143cecb4c76a8d6efca1 to your computer and use it in GitHub Desktop.
Save taoky/db7d1dab5b14143cecb4c76a8d6efca1 to your computer and use it in GitHub Desktop.
package main
import (
"bufio"
"flag"
"fmt"
"log"
"os"
"os/exec"
"strings"
"github.com/fatih/color"
)
func main() {
shellPtr := flag.Bool("shell", false, "Use shell (/bin/sh) to execute program")
flag.Parse()
if len(flag.Args()) == 0 {
fmt.Println("Missing program to be executed. Append it after parameters.")
fmt.Printf("Example: %s ls -lh\n", os.Args[0])
fmt.Printf("%s -shell echo '$PWD'\n", os.Args[0])
os.Exit(-1)
}
program := flag.Args()
yellow := color.New(color.FgYellow).SprintFunc()
red := color.New(color.FgRed).SprintFunc()
fmt.Printf("%s: Executing\n", yellow(program))
var cmd *exec.Cmd = nil
if *shellPtr {
shellArgs := []string{"-c"}
shellArgs = append(shellArgs, strings.Join(program, " "))
cmd = exec.Command("sh", shellArgs...)
} else {
cmd = exec.Command(program[0], program[1:]...)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.Fatalf("%s cmd.StderrPipe(): %v", yellow(program), err)
}
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatalf("%s cmd.StdoutPipe(): %v", yellow(program), err)
}
err = cmd.Start()
if err != nil {
log.Fatalf("%s cmd.Start(): %v", yellow(program), err)
}
pid := cmd.Process.Pid
displayedName := yellow(program) + " " + red(pid)
fmt.Printf("%s: PID=%s\n", yellow(program), red(pid))
stdoutScanner := bufio.NewScanner(stdout)
isStdoutFinished := make(chan bool)
go func(fin chan bool) {
for stdoutScanner.Scan() {
fmt.Printf("%s stdout: %s\n", displayedName, stdoutScanner.Text())
}
fin <- true
}(isStdoutFinished)
stderrScanner := bufio.NewScanner(stderr)
isStderrFinished := make(chan bool)
go func(fin chan bool) {
for stderrScanner.Scan() {
fmt.Fprintf(os.Stderr, "%s stderr: %s\n", displayedName, stderrScanner.Text())
}
fin <- true
}(isStderrFinished)
<-isStdoutFinished
<-isStderrFinished
err = cmd.Wait()
if err != nil {
if exitError, ok := err.(*exec.ExitError); ok {
log.Printf("%s exited with status %d", displayedName, exitError.ExitCode())
} else {
log.Fatalf("%s cmd.Wait(): %v", displayedName, err)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment