mirror of
https://github.com/lzh-1625/go_process_manager.git
synced 2025-09-26 20:11:20 +08:00
112 lines
2.5 KiB
Go
112 lines
2.5 KiB
Go
package main
|
|
|
|
import (
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"os/exec"
|
|
|
|
"github.com/creack/pty"
|
|
"github.com/gorilla/websocket"
|
|
)
|
|
|
|
var upgrader = websocket.Upgrader{
|
|
CheckOrigin: func(r *http.Request) bool {
|
|
return true
|
|
},
|
|
}
|
|
|
|
func main() {
|
|
http.HandleFunc("/ws", handleWebSocket)
|
|
log.Println("Server started at :8080")
|
|
log.Fatal(http.ListenAndServe(":8080", nil))
|
|
}
|
|
|
|
func handleWebSocket(w http.ResponseWriter, r *http.Request) {
|
|
conn, err := upgrader.Upgrade(w, r, nil)
|
|
if err != nil {
|
|
log.Println("Upgrade:", err)
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
|
|
// 启动 Minecraft 服务器
|
|
cmd := exec.Command("java", "-jar", "launcher-airplane.jar")
|
|
|
|
// 创建伪终端
|
|
ptmx, err := pty.Start(cmd)
|
|
if err != nil {
|
|
log.Println("Start pty:", err)
|
|
return
|
|
}
|
|
defer func() { _ = ptmx.Close() }() // 最后关闭伪终端
|
|
|
|
// 创建通道用于读取子程序的输出
|
|
outputChan := make(chan string)
|
|
|
|
go func() {
|
|
defer close(outputChan)
|
|
readOutput(ptmx, outputChan)
|
|
}()
|
|
|
|
// 将子程序的输出发送到 WebSocket 客户端
|
|
go func() {
|
|
for output := range outputChan {
|
|
if err := conn.WriteMessage(websocket.TextMessage, []byte(output)); err != nil {
|
|
log.Println("WriteMessage:", err)
|
|
break
|
|
}
|
|
}
|
|
}()
|
|
|
|
// 从 WebSocket 客户端读取消息并发送到子程序的标准输入
|
|
for {
|
|
_, message, err := conn.ReadMessage()
|
|
if err != nil {
|
|
log.Println("ReadMessage:", err)
|
|
break
|
|
}
|
|
// 检查是否是发送 Tab 键的命令
|
|
if string(message) == "SEND_TAB" {
|
|
_, err := ptmx.Write([]byte{9}) // Tab 键的 ASCII 码是 9
|
|
if err != nil {
|
|
log.Println("Write to stdin:", err)
|
|
}
|
|
} else if string(message) == "READ_INPUT" {
|
|
// 读取伪终端当前输入管道内已经存在的内容
|
|
// 注意:伪终端没有单独的输入缓冲区,输入会立即被处理
|
|
// 这里假设你想获取当前输出内容
|
|
if err := conn.WriteMessage(websocket.TextMessage, []byte("Currently no direct way to fetch unsent input. Consider monitoring the terminal buffer.")); err != nil {
|
|
log.Println("WriteMessage:", err)
|
|
}
|
|
} else {
|
|
_, err := ptmx.Write(append(message, '\n')) // 确保命令后有换行符
|
|
if err != nil {
|
|
log.Println("Write to stdin:", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 等待子程序结束
|
|
if err := cmd.Wait(); err != nil {
|
|
log.Println("Wait:", err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func readOutput(reader io.Reader, outputChan chan<- string) {
|
|
buf := make([]byte, 1024)
|
|
for {
|
|
n, err := reader.Read(buf)
|
|
if n > 0 {
|
|
outputChan <- string(buf[:n])
|
|
}
|
|
if err != nil {
|
|
if err != io.EOF {
|
|
log.Println("Read:", err)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|