Skip to content

Instantly share code, notes, and snippets.

@EFulmer
Last active August 29, 2015 14:04
Show Gist options
  • Save EFulmer/bcde405b38442bd74c2c to your computer and use it in GitHub Desktop.
Save EFulmer/bcde405b38442bd74c2c to your computer and use it in GitHub Desktop.
Building a simple Cron utility to update my Homebrew packages
// first version:
// just runs "brew update", waits for result, and exits
package main
import (
"os/exec"
)
func main() {
cmd := exec.Command("brew", "update")
cmd.Run()
}
// second version:
// notifies user that brew update will be run, prints command's stdout & err
package main
import (
"bytes"
"fmt"
"os/exec"
)
func main() {
cmd := exec.Command("brew", "update")
var out bytes.Buffer
var err bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &err
fmt.Println("Running brew update now...")
cmd.Run()
fmt.Printf("Stdout from brew update: %q\n", out.String())
fmt.Printf("Stderr from brew update: %q\n", err.String())
}
// third version
// runs a timer and writes results to a log file
package main
import (
"bytes"
"log"
"os"
"os/exec"
"path"
"time"
)
const LOG_FILE_NAME = ".brew_update_log"
func AppendFile(name string) (*os.File, error) {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return os.Create(name)
}
}
return os.OpenFile(name, os.O_APPEND | os.O_RDWR, 0660)
}
func main() {
cmd := exec.Command("brew", "update")
var bufout bytes.Buffer
var buferr bytes.Buffer
home := os.Getenv("HOME")
logPath := path.Join(home, LOG_FILE_NAME)
logFile, err := AppendFile(logPath)
if err != nil {
log.Fatal(err)
}
defer logFile.Close()
cmd.Stdout = &bufout
cmd.Stderr = &buferr
start := time.Now()
cmd.Run()
elapsed := time.Since(start)
logFile.WriteString(start.String())
logFile.WriteString("\nTime needed to run: ")
logFile.WriteString(elapsed.String())
logFile.WriteString("\nStdout from brew update: ")
logFile.WriteString(bufout.String())
logFile.WriteString("\nStderr from brew update: ")
logFile.WriteString(buferr.String())
logFile.WriteString("\n\n")
}
// fourth version
// checks for network connection asynchronously
package main
import (
"bytes"
"fmt"
"log"
"net"
"os"
"os/exec"
"path"
"time"
)
const LOG_FILE_NAME = ".brew_update_log"
func AppendFile(name string) (*os.File, error) {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return os.Create(name)
}
}
return os.OpenFile(name, os.O_APPEND | os.O_RDWR, 0660)
}
func testConn(status chan error) {
conn, err := net.Dial("tcp", "google.com:80")
status <- err
if err == nil {
conn.Close()
}
}
func main() {
cmd := exec.Command("/usr/local/bin/brew", "update")
var bufout bytes.Buffer
var buferr bytes.Buffer
home := os.Getenv("HOME")
logPath := path.Join(home, LOG_FILE_NAME)
logFile, err := AppendFile(logPath)
if err != nil {
log.Fatal(err)
}
defer logFile.Close()
status := make(chan error)
go testConn(status)
cmd.Stdout = &bufout
cmd.Stderr = &buferr
start := time.Now()
err = cmd.Run()
elapsed := time.Since(start)
timeTaken := fmt.Sprintf("\nTime needed to run: %v\n", elapsed.String())
stdOut := fmt.Sprintf("Stdout from brew update: %v\n", bufout.String())
stdErr := fmt.Sprintf("Stderr from brew update: %v\n", buferr.String())
logFile.WriteString(start.String())
netStat := <-status
if netStat != nil {
errMsg := fmt.Sprintf("Network error encountered: %v\n", netStat.Error())
log.Print(errMsg)
logFile.WriteString(errMsg)
}
if err != nil {
errMsg := fmt.Sprintf("Error encountered in executing brew update: %v\n",
err.Error())
logFile.WriteString(errMsg)
log.Fatal(errMsg)
}
logFile.WriteString(timeTaken)
logFile.WriteString(stdOut)
logFile.WriteString(stdErr)
logFile.WriteString("\n")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment