Skip to content

Commit

Permalink
service/internal.RunOutput: fix both #110 and #156 properly
Browse files Browse the repository at this point in the history
  • Loading branch information
rs committed Apr 16, 2020
1 parent fcf3fdc commit 722778d
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 26 deletions.
51 changes: 27 additions & 24 deletions host/service/internal/run_unix.go
@@ -1,7 +1,7 @@
package internal

import (
"bufio"
"bytes"
"context"
"errors"
"fmt"
Expand All @@ -17,40 +17,43 @@ func Run(command string, arguments ...string) error {
return err
}

func RunOutput(command string, args ...string) (string, error) {
var stdout string
func RunOutput(command string, args ...string) (out string, err error) {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
var stdout, stderr bytes.Buffer
defer func() {
cancel()
if err != nil {
err = fmt.Errorf("%s %s: %w: %s", command, strings.Join(args, " "), err, stderr.String())
}
}()
cmd := exec.CommandContext(ctx, command, args...)
// Obtain a pipe connected to our cmd stdout so we can read from it later.
// cmd.Output() would block here because the underlying pipes are not closed
// and it will try to read from them indefinitely
stdoutPipe, err := cmd.StdoutPipe()
if err != nil {
cancel()
return "", fmt.Errorf("%s %s: %w", command, strings.Join(args, " "), err)
var stdoutPipe, stderrPipe io.ReadCloser
if stdoutPipe, err = cmd.StdoutPipe(); err != nil {
err = fmt.Errorf("cannot connect stdout: %w", err)
return
}
if stderrPipe, err = cmd.StderrPipe(); err != nil {
err = fmt.Errorf("cannot connect stderr: %w", err)
return
}
if err = cmd.Start(); err != nil {
cancel()
return "", fmt.Errorf("%s %s: %w", command, strings.Join(args, " "), err)
return
}
go func(stdout string, stdoutPipe io.ReadCloser) {
buf := bufio.NewReader(stdoutPipe)
for {
line, _ := buf.ReadString('\n')
if len(line) > 0 {
stdout = stdout + line + "\n"
}
}
}(stdout, stdoutPipe)
err = cmd.Wait()
if err != nil {
cancel()
return "", fmt.Errorf("%s %s: %w", command, strings.Join(args, " "), err)
go copy(&stdout, stdoutPipe)
go copy(&stderr, stderrPipe)
if err = cmd.Wait(); err != nil {
return
}
return stdout, nil
out = strings.TrimSpace(stdout.String())
return
}

func copy(w io.Writer, r io.ReadCloser) {
_, _ = io.Copy(w, r)
}
func ExitCode(err error) int {
if err == nil {
return 0
Expand Down
2 changes: 0 additions & 2 deletions host/service/systemd/service.go
Expand Up @@ -4,7 +4,6 @@ package systemd

import (
"errors"
"fmt"
"os"
"os/exec"
"strings"
Expand Down Expand Up @@ -53,7 +52,6 @@ func (s Service) Uninstall() error {

func (s Service) Status() (service.Status, error) {
out, err := internal.RunOutput("systemctl", "is-active", s.Name)
fmt.Println(out, err)
if internal.ExitCode(err) == 0 && err != nil {
return service.StatusUnknown, err
}
Expand Down

0 comments on commit 722778d

Please sign in to comment.