Answer the question
In order to leave comments, you need to log in
How to work with an external process from GO?
Hey!
Another one of my attempts to ask how to implement such a thing: a
Go program starts an external process through exec.Command, let's call it a worker .
The worker is a simple echo server that receives a string on stdin and returns it back.
How not to produce and not restart the process-worker (i.e., they started it and it is constantly spinning in memory), constantly (in a loop) write to it on stdin and read from stdout / err. Those. to implement work with it in the query string mode, and the response as an echo of this string as a response?
A lot of material about channels, go-routines and running processes, but I did not find such an example. Help me please.
Answer the question
In order to leave comments, you need to log in
In the end, it worked for me like this:
package main
import (
"io"
"fmt"
"log"
"bufio"
"os/exec"
"strconv"
)
func get_err(id string, stderr io.ReadCloser, errs chan<- string) {
defer stderr.Close()
rd_err := bufio.NewReader(stderr)
for {
err_line, _, err := rd_err.ReadLine()
if err != nil {
if err == io.EOF {
fmt.Println("Exit by EOF...")
}
fmt.Println("Error reading stdout:", err)
return
}
errs <- id+" - "+string(err_line)
}
}
func worker(id int, tasks <-chan string, status chan string, errors chan string) {
// выставляем настройки запуска воркера
cmd := exec.Command("perl", "./worker.pl")
stdin, err := cmd.StdinPipe()
if err != nil {
log.Panic(err)
}
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Panic(err)
}
stderr, err := cmd.StderrPipe()
if err != nil {
log.Panic(err)
}
go get_err(strconv.Itoa(id),stderr, errors)
err = cmd.Start()
if err != nil {
log.Panic(err)
}
rd := bufio.NewReader(stdout)
for {
t := <- tasks
task_id := t[0]
task := t[1:len(t)]
stdin.Write([]byte(task))
fmt.Println("STDIN " + strconv.Itoa(id) + " >>> " + " - task " + string(task_id) + " " + task)
line, _, err := rd.ReadLine()
if err != nil {
if err == io.EOF {
fmt.Println("Exit by EOF...")
}
fmt.Println("Error reading stdout:", err)
return
}
status <- strconv.Itoa(id)+" - task "+string(task_id)+" "+string(line)+"\n"
}
err = cmd.Wait()
if err != nil {
log.Panic(err)
}
}
func main() {
test_words := []string{`raz`, `dva`, `tri`,}
tasks := make(chan string)
status := make(chan string)
errors := make(chan string)
go func(){
for {
bad := <- errors
fmt.Println("<<< STDERR ", bad)
}
}()
go func(){
for {
req := <- status
fmt.Println("<<< STDOUT ", req)
}
}()
// запуск воркера
go worker(w, tasks, status, errors)
// приём/передача запросов/ответов
for i := 0; i < len(test_words); i++ {
tasks <- strconv.Itoa(i)+test_words[i]+"\n"
}
}
https://golang.org/pkg/os/exec/
or rather
https://golang.org/pkg/os/exec/#Cmd.StdinPipe
https://golang.org/pkg/os/exec/#Cmd .StdoutPipe
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question