Golang实现终端输出到Web服务器的方案

Golang实现终端输出到Web服务器的方案 你好,我对Go语言还比较陌生。我正在创建一个带有API的应用程序,用户需要提供输入。之后,终端会有一个输出。我想把这个终端的输出显示在我的网页服务器上。

我已经创建了一个网页服务器(http localhost:8080),但我就是不知道如何将终端的输出传送到网页服务器。

1 回复

更多关于Golang实现终端输出到Web服务器的方案的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


一种常见方案是使用WebSocket实现实时输出传输。以下是完整示例:

package main

import (
    "fmt"
    "log"
    "net/http"
    "os/exec"
    "time"

    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool { return true },
}

// WebSocket处理器
func handleWebSocket(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println("WebSocket升级失败:", err)
        return
    }
    defer conn.Close()

    // 执行终端命令并实时传输输出
    cmd := exec.Command("bash", "-c", "for i in {1..10}; do echo '输出行: $i'; sleep 1; done")
    
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        conn.WriteMessage(websocket.TextMessage, []byte("错误: 无法获取输出管道"))
        return
    }

    if err := cmd.Start(); err != nil {
        conn.WriteMessage(websocket.TextMessage, []byte("错误: 命令执行失败"))
        return
    }

    // 实时读取输出并发送到WebSocket
    buf := make([]byte, 1024)
    for {
        n, err := stdout.Read(buf)
        if n > 0 {
            conn.WriteMessage(websocket.TextMessage, buf[:n])
        }
        if err != nil {
            break
        }
    }
    
    cmd.Wait()
}

// 网页服务器
func main() {
    http.HandleFunc("/ws", handleWebSocket)
    
    // 提供HTML页面
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        html := `
        <!DOCTYPE html>
        <html>
        <head>
            <title>终端输出</title>
        </head>
        <body>
            <h2>实时终端输出:</h2>
            <pre id="output" style="background:#f0f0f0;padding:10px;"></pre>
            <script>
                const ws = new WebSocket('ws://' + window.location.host + '/ws');
                ws.onmessage = function(event) {
                    document.getElementById('output').textContent += event.data;
                };
                ws.onerror = function(error) {
                    document.getElementById('output').textContent = '连接错误';
                };
            </script>
        </body>
        </html>`
        fmt.Fprint(w, html)
    })

    log.Println("服务器启动: http://localhost:8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

如果不需要实时传输,可以使用轮询方案:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "log"
    "net/http"
    "os/exec"
    "sync"
)

var (
    outputBuffer bytes.Buffer
    bufferMutex  sync.RWMutex
)

// 执行终端命令并捕获输出
func executeCommand() {
    cmd := exec.Command("ls", "-la")
    output, err := cmd.CombinedOutput()
    
    bufferMutex.Lock()
    defer bufferMutex.Unlock()
    outputBuffer.Reset()
    if err != nil {
        outputBuffer.WriteString(fmt.Sprintf("错误: %v\n", err))
    }
    outputBuffer.Write(output)
}

// API端点:获取终端输出
func getOutput(w http.ResponseWriter, r *http.Request) {
    bufferMutex.RLock()
    defer bufferMutex.RUnlock()
    
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(map[string]string{
        "output": outputBuffer.String(),
    })
}

// API端点:触发命令执行
func runCommand(w http.ResponseWriter, r *http.Request) {
    go executeCommand()
    w.WriteHeader(http.StatusAccepted)
    fmt.Fprint(w, "命令执行中...")
}

func main() {
    http.HandleFunc("/api/output", getOutput)
    http.HandleFunc("/api/run", runCommand)
    
    // 静态页面
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        html := `
        <!DOCTYPE html>
        <html>
        <body>
            <button onclick="runCommand()">执行命令</button>
            <pre id="output"></pre>
            <script>
                async function runCommand() {
                    await fetch('/api/run');
                    setTimeout(fetchOutput, 1000);
                }
                async function fetchOutput() {
                    const res = await fetch('/api/output');
                    const data = await res.json();
                    document.getElementById('output').textContent = data.output;
                }
            </script>
        </body>
        </html>`
        fmt.Fprint(w, html)
    })

    log.Println("服务器启动: http://localhost:8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

安装依赖:

go get github.com/gorilla/websocket

第一个示例使用WebSocket实现实时输出,适合长时间运行的命令。第二个示例使用轮询方式,适合快速完成的命令。根据实际需求选择合适方案。

回到顶部