The child process is not exiting when I issue the exit
command and the TCP server returns the original command with output. I have a simple Golang TCP server like the one below
package main
import (
"fmt"
"net"
"os"
"os/exec"
)
func handleConn(conn net.Conn) {
defer conn.Close()
cmd := exec.Command("powershell.exe")
cmd.Stdin = conn
cmd.Stdout = conn
cmd.Stderr = conn
if err := cmd.Start(); err != nil {
panic(err)
}
if err := cmd.Wait(); err != nil {
panic(err)
}
fmt.Fprintf(os.Stderr, "Connection closed\n")
}
func main() {
// create listening socket
ln, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Fprintf(os.Stderr, "Error Occured: %s", err.Error())
return
}
// below line will run when main returns
defer ln.Close()
// accept connections one by one
for {
// accept new connection
conn, err := ln.Accept()
if err != nil {
fmt.Fprintf(os.Stderr, "Error accepting connection: %s\n", err.Error())
continue
}
go handleConn(conn)
}
}
Then I try to connect it using socat
like below,
socat tcp4:127.0.0.1:8080 -
But every time, I pass something, the TCP server echoes the command with the output like below,
And also when I pass the exit
command, the child process is not exiting. I had to press ctrl+c then it closes the TCP connection and then the child process exits.
I am using Windows.
The child process is not exiting when I issue the exit
command and the TCP server returns the original command with output. I have a simple Golang TCP server like the one below
package main
import (
"fmt"
"net"
"os"
"os/exec"
)
func handleConn(conn net.Conn) {
defer conn.Close()
cmd := exec.Command("powershell.exe")
cmd.Stdin = conn
cmd.Stdout = conn
cmd.Stderr = conn
if err := cmd.Start(); err != nil {
panic(err)
}
if err := cmd.Wait(); err != nil {
panic(err)
}
fmt.Fprintf(os.Stderr, "Connection closed\n")
}
func main() {
// create listening socket
ln, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Fprintf(os.Stderr, "Error Occured: %s", err.Error())
return
}
// below line will run when main returns
defer ln.Close()
// accept connections one by one
for {
// accept new connection
conn, err := ln.Accept()
if err != nil {
fmt.Fprintf(os.Stderr, "Error accepting connection: %s\n", err.Error())
continue
}
go handleConn(conn)
}
}
Then I try to connect it using socat
like below,
socat tcp4:127.0.0.1:8080 -
But every time, I pass something, the TCP server echoes the command with the output like below,
And also when I pass the exit
command, the child process is not exiting. I had to press ctrl+c then it closes the TCP connection and then the child process exits.
I am using Windows.
Share Improve this question edited Nov 21, 2024 at 9:03 PSKP asked Nov 20, 2024 at 18:01 PSKPPSKP 1,37417 silver badges38 bronze badges 2 |1 Answer
Reset to default 0The truth is that they recommend you use Pipe, something like this:
package main
import (
"fmt"
"io"
"net"
"os"
"os/exec"
)
func handleConn(conn net.Conn) {
defer conn.Close()
// The command to run the terminal in my case is /bin/bash is Linux
// cmd := exec.Command("/bin/bash")
// you case use this:
cmd := exec.Command("powershell.exe")
// Set the stdin, stdout, stderr of the command to the connection
stdIn, err := cmd.StdinPipe()
if err != nil {
panic(err)
}
stdOut, err := cmd.StdoutPipe()
if err != nil {
panic(err)
}
stdErr, err := cmd.StderrPipe()
if err != nil {
panic(err)
}
// Read from the connection and write to the stdin of the command
go func() {
for {
line := make([]byte, 1024)
l, _ := conn.Read(line)
//windows remove echo
for i := 0; i < l; i++ {
conn.Write([]byte("\b"))
}
stdIn.Write(line[:l])
}
}()
go func() {
buf := make([]byte, 1024)
for {
n, err := stdOut.Read(buf)
if err == io.EOF {
conn.Write([]byte("Terminal closed\n"))
os.Stdout.Write([]byte("connection from " + conn.RemoteAddr().String() + " Terminal closed\n"))
break
}
conn.Write(buf[:n])
}
}()
go func() {
buf := make([]byte, 1024)
for {
n, _ := stdErr.Read(buf)
conn.Write(buf[:n])
}
}()
if err := cmd.Run(); err != nil {
panic(err)
}
// In this point the command has finished and the connection is closed
// if you want to keep the connection open you can do something else
// example:
//conn.Write([]byte("other text to send \n"))
}
func main() {
// create listening socket
ln, err := net.Listen("tcp", ":8080")
if err != nil {
fmt.Fprintf(os.Stderr, "Error Occured: %s", err.Error())
return
}
// below line will run when main returns
defer ln.Close()
// accept connections one by one
for {
// accept new connection
conn, err := ln.Accept()
if err != nil {
fmt.Fprintf(os.Stderr, "Error accepting connection: %s\n", err.Error())
continue
}
go handleConn(conn)
}
}
defer conn.Close()
which will happen afterWait
, butWait
can't return until the connection closes. – Mr_Pink Commented Nov 20, 2024 at 18:05exit
, the child process should exit. – PSKP Commented Nov 21, 2024 at 7:49