Я пытаюсь перехватить вывод команды в том виде, в каком она происходит, чтобы я мог передать sh это как буферизованные данные HTTP-клиенту, но я не правильно использую каналы и не знаю, как это исправить.
По сути, это то, как я это реализую. Выходной канал никогда не принимается, и я не получаю вывод команды. Это должно быть что-то довольно очевидное, но я этого не вижу.
package main
import (
"bufio"
"fmt"
"io"
"log"
"os/exec"
)
func main() {
output := make(chan []byte, 1024)
done := make(chan struct{})
cmd := exec.Command("echo", "hello")
go execute(cmd, output, done)
for {
select {
case data := <-output:
fmt.Println("Got data")
fmt.Println(string(data))
//Flush to http.ResponseWriter
case <-done:
fmt.Println("Done")
return
}
}
}
func execute(cmd *exec.Cmd, output chan []byte, done chan struct{}) {
defer func() {
done <- struct{}{}
}()
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println(err)
output <- []byte(fmt.Sprintf("Error getting stdout pipe: %v", err))
return
}
stderr, err := cmd.StderrPipe()
if err != nil {
fmt.Println(err)
output <- []byte(fmt.Sprintf("Error getting stderr pipe: %v", err))
return
}
scanner := bufio.NewScanner(io.MultiReader(stdout, stderr))
err = cmd.Start()
if err != nil {
fmt.Println(err)
output <- []byte(fmt.Sprintf("Error executing: %v", err))
return
}
go func() {
for scanner.Scan() {
fmt.Println(string(scanner.Bytes()))
output <- scanner.Bytes()
fmt.Println("Sent data")
}
}()
err = cmd.Wait()
if err != nil {
fmt.Println(err)
output <- []byte(fmt.Sprintf("Error waiting for the script to complete: %v", err))
return
}
}
РЕДАКТИРОВАТЬ:
После некоторых размышлений, вот обновленный код. Это работает, как я ожидаю, но все еще не уверен, правильно ли я делаю. Я удалил готовый канал и диапазон по выходному каналу. Он получает все данные из вывода, отправленные через сканер при выполнении, и не блокируется, так как вывод закрыт после завершения команды. Это не печатает «привет» на Go Playground, но я получаю ожидаемое поведение в моем проекте.
Буду признателен за отзыв.
package main
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
)
func main() {
output := make(chan []byte)
cmd := exec.Command("echo", "hello")
go execute(cmd, output)
for data := range output {
fmt.Println(string(data))
}
}
func execute(cmd *exec.Cmd, output chan []byte) {
defer close(output)
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println(err)
output <- []byte(fmt.Sprintf("Error getting stdout pipe: %v", err))
return
}
cmd.Stderr = cmd.Stdout
scanner := bufio.NewScanner(stdout)
done := make(chan struct{})
err = cmd.Start()
if err != nil {
output <- []byte(fmt.Sprintf("Error executing: %v", err))
return
}
go func() {
for scanner.Scan() {
output <- scanner.Bytes()
}
done <- struct{}{}
}()
<-done
err = cmd.Wait()
if err != nil {
fmt.Println(err)
output <- []byte(fmt.Sprintf("Error waiting for the script to complete: %v", err))
}
}