在我的程序中,我希望能够真实的监控一些控制台命令的执行。
下面是两个在控制台中真实的显示数据的代码示例,但在网页上数据并不是实时显示的,而是仅在命令完成后才显示。
请告诉我如何在网页中获得真实的数据?
- 在这两个例子中:控制台真实的显示数据。在网页上,数据不是实时显示,而是在命令完成后才显示。我需要在网页上实时显示数据。*
实施例1
package main
import (
"bytes"
"fmt"
"log"
"net/http"
"os"
"os/exec"
"io"
)
func main() {
http.HandleFunc("/", mainLogic)
http.ListenAndServe(":8080", nil)
}
func mainLogic(w http.ResponseWriter, r *http.Request) {
cmd := exec.Command("ping", "8.8.8.8", "-c5")
var stdBuffer bytes.Buffer
mw := io.MultiWriter(os.Stdout, &stdBuffer)
cmd.Stdout = mw
cmd.Stderr = mw
if err := cmd.Run(); err != nil {
log.Panic(err)
}
fmt.Fprintf(w, stdBuffer.String())
}
实施例2
package main
import (
"fmt"
"log"
"net/http"
"os"
"os/exec"
"io"
"sync"
)
func main() {
http.HandleFunc("/", mainLogic)
http.ListenAndServe(":8080", nil)
}
func mainLogic(w http.ResponseWriter, r *http.Request) {
cmd := exec.Command("ping", "8.8.8.8", "-c5")
var stdout []byte
var errStdout, errStderr error
stdoutIn, _ := cmd.StdoutPipe()
stderrIn, _ := cmd.StderrPipe()
err := cmd.Start()
if err != nil {
log.Fatalf("cmd.Start() failed with '%s'\n", err)
}
var wg sync.WaitGroup
wg.Add(1)
go func() {
stdout, errStdout = copyAndCapture(os.Stdout, stdoutIn)
wg.Done()
}()
_, errStderr = copyAndCapture(os.Stderr, stderrIn)
wg.Wait()
err = cmd.Wait()
if err != nil {
log.Fatalf("cmd.Run() failed with %s\n", err)
}
if errStdout != nil || errStderr != nil {
log.Fatal("failed to capture stdout or stderr\n")
}
fmt.Fprintf(w, string(stdout))
}
func copyAndCapture(w io.Writer, r io.Reader) ([]byte, error) {
var out []byte
buf := make([]byte, 1024, 1024)
for {
n, err := r.Read(buf[:])
if n > 0 {
d := buf[:n]
out = append(out, d...)
_, err := w.Write(d)
if err != nil {
return out, err
}
}
if err != nil {
if err == io.EOF {
err = nil
}
return out, err
}
}
}
1条答案
按热度按时间l7wslrjt1#
出于性能原因,HTTP响应默认情况下是缓冲的,因此您需要显式调用
Flush
以立即发送数据。如果你想从一个分配给
exec.Cmd
输出的writer中完成这个任务,你可以将http.ResponseWriter
Package 在一个类型中,这个类型将在每个Write
上为你调用Flush
。如果你想要一份数据的拷贝,你可以使用
io.MultiWriter
在输出被写入的时候捕获它。这里我们还介绍了http.ResponseWriter
不是http.Flusher
的情况,但是只有当你已经通过其他中间件 Package 时才可能发生这种情况。