-
Hello, good time! I have this project (name it goterm) which opens your local terminal in web via websocket connection... used xtermjs to simulate terminal in web. Here is how I open a PTY: cmd := exec.Command("/bin/bash", "-l")
cmd.Env = append(os.Environ(), "TERM=xterm")
tty, err := pty.Start(cmd)
if err != nil {
l.WithError(err).Error("Unable to start pty/cmd")
conn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
return
}
defer func() {
cmd.Process.Kill()
cmd.Process.Wait()
tty.Close()
conn.Close()
}() BUT my problem comes, when I want to combine this with my other project. My other project is almost the same with above one, but with some differences, let me tell scenario: Here is my code: func main() {
// load environment
err := godotenv.Load("/etc/htopNovin/config")
if err != nil {
//log.Fatal("Error loading .env file")
}
if len(os.Args) > 1 {
args := os.Args[1]
if args == "version" && len(os.Args) == 2 {
fmt.Println(version)
} else if args == "setup" && len(os.Args) == 2 {
// service permission
check_permission()
setup()
} else if args == "update" && len(os.Args) == 2 {
// service permission
check_permission()
update()
} else {
fmt.Println("you paramts is invalid")
}
} else {
// service permission
check_permission()
go servTerm() // <- where I wish to open a PTY
serversocket() // <- where I start my websocket connection to my server, for sending data in periodic time
}
} The But when I run my project and request to my URL, I'll get this error: Here is my code: func handleWebsocket(w http.ResponseWriter, r *http.Request) {
// l := log.WithField("remoteaddr", r.RemoteAddr)
conn, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Println("Unable to upgrade connection")
return
}
cmd := exec.Command("/bin/bash", "-l")
cmd.Env = append(os.Environ(), "TERM=xterm")
tty, err := pty.Start(cmd)
if err != nil {
log.Printf("Unable to start pty/cmd. error: %v \n", err)
conn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
return
}
defer func() {
cmd.Process.Kill()
cmd.Process.Wait()
tty.Close()
conn.Close()
}()
// WRITE MESSAGE
go func() {
for {
buf := make([]byte, 1024)
read, err := tty.Read(buf)
if err != nil {
conn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
log.Printf("Unable to read from pty/cmd %d \n", err)
return
}
conn.WriteMessage(websocket.BinaryMessage, buf[:read])
}
}()
// END WRITE MESSAGE
// READ MESSAGE
for {
messageType, reader, err := conn.NextReader()
if err != nil {
log.Println("Unable to grab next reader")
return
}
if messageType == websocket.TextMessage {
log.Println("Unexpected text message")
conn.WriteMessage(websocket.TextMessage, []byte("Unexpected text message"))
continue
}
dataTypeBuf := make([]byte, 1)
read, err := reader.Read(dataTypeBuf)
if err != nil {
conn.WriteMessage(websocket.TextMessage, []byte("Unable to read message type from reader"))
return
}
if read != 1 {
log.Println("Unexpected number of bytes read")
conn.WriteMessage(websocket.TextMessage, []byte("Unexpected text message"))
return
}
switch dataTypeBuf[0] {
case 0:
copied, err := io.Copy(tty, reader)
if err != nil {
// l.WithError(err).Errorf("Error after copying %d bytes", copied)
log.Printf("Error after copying %d bytes", copied)
}
case 1:
decoder := json.NewDecoder(reader)
resizeMessage := windowSize{}
err := decoder.Decode(&resizeMessage)
if err != nil {
conn.WriteMessage(websocket.TextMessage, []byte("Error decoding resize message: "+err.Error()))
continue
}
// log.WithField("resizeMessage", resizeMessage).Info("Resizing terminal")
log.Println("Resizing terminal")
_, _, errno := syscall.Syscall(
syscall.SYS_IOCTL,
tty.Fd(),
syscall.TIOCSWINSZ,
uintptr(unsafe.Pointer(&resizeMessage)),
)
if errno != 0 {
// l.WithError(syscall.Errno(errno)).Error("Unable to resize terminal")
}
default:
log.Println("Unknown data type")
}
}
// END READ MESSAGE
}
func servTerm() {
var listen = flag.String("listen", "127.0.0.1:3000", "Host:port to listen on")
var assetsPath = flag.String("assets", "./assets", "Path to assets")
flag.Parse()
r := mux.NewRouter()
r.HandleFunc("/term", handleWebsocket)
r.PathPrefix("/").Handler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Get the requested file path from the URL.
requestedFile := r.URL.Path
// Use the filepath.Ext function to extract the file extension.
// This will be used to determine the appropriate Content-Type.
fileExt := filepath.Ext(requestedFile)
// Set the appropriate Content-Type header based on the file extension.
if contentType, ok := mimeTypes[fileExt]; ok {
w.Header().Set("Content-Type", contentType)
}
// Serve the file using the file server.
http.FileServer(http.Dir(*assetsPath)).ServeHTTP(w, r)
}))
if !(strings.HasPrefix(*listen, "127.0.0.1") || strings.HasPrefix(*listen, "localhost")) {
// log.Warn("Danger Will Robinson - This program has no security built in and should not be exposed beyond localhost, you've been warned")
log.Println("Danger Will Robinson - This program has no security built in and should not be exposed beyond localhost, you've been warned")
}
if err := http.ListenAndServe(*listen, r); err != nil {
// log.WithError(err).Fatal("Something went wrong with the webserver")
log.Println("Something went wrong with the webserver")
}
} Can someone please help me with my problem? Anyhow, thanks a lot! |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
I found the solution! the version I was using was old! use the latest version and also remember to change it in go.mod and go.sum files. Have nice time... |
Beta Was this translation helpful? Give feedback.
I found the solution! the version I was using was old! use the latest version and also remember to change it in go.mod and go.sum files.
Have nice time...