чтение из cmd.StdoutPipe () - PullRequest
0 голосов
/ 06 августа 2020

Обратите внимание на этот Go код:

package main

import (
    "fmt"
    "os/exec"
    "strings"
    "time"
)

const (
    debugCmd = "/usr/bin/libinput debug-events"
    //debugCmd = "tail -f /tmp/syslog"
)

func main() {
    fmt.Println("Hello!")
    fmt.Println("cmd", debugCmd)
    cmdSplat := strings.Split(debugCmd, " ")
    cmd := exec.Command(cmdSplat[0], cmdSplat[1:]...)
    stdOut, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Println("cmd.StdOut failed", err)
    }
    defer stdOut.Close()

    go func() {
        tempBuf := make([]byte, 1024)
        for {
            n, err := stdOut.Read(tempBuf)
            if n > 0 {
                fmt.Printf("Read: %d bytes, err: %v\n", n, err)
                someSlice := tempBuf[:n]
                fmt.Println("text", string(someSlice))
            } else {
                fmt.Printf("Zero Read :%d, err: %v", n, err)
            }

        }
    }()

    fmt.Println("STarting cmd")
    err = cmd.Start()
    if err != nil {
        fmt.Println("cmd.start", err)
    }
    fmt.Println("All done!")
    // cmd.Wait()
    time.Sleep(60 * time.Second)
    fmt.Println("Done sleeping!")

}

В реальной жизни он набирает значение только после того, как прочитает 1024 байта. Раньше у меня это было с использованием bufio, но это тоже было медленным:

go func() {
    r := bufio.NewReader(stdOut)
    for {
        line, err := r.ReadString('\n')
        if err != nil {
            fmt.Println("End of things!")
            break
        }
        fmt.Print(line)

    }
}()

Моя цель - забрать debug-events из stdOut io.ReadCloser достаточно быстро - по мере их появления и появления - вместо пакетов с водяным знаком 1024 байта.

Вот мой результат:

Read: 1024 bytes, err: <nil> // <------------ this 
text finger)
 event5   POINTER_AXIS     +2.380s  vert -11.14/0* horiz 10.75/0* (finger)
 event5   POINTER_AXIS     +2.400s  vert -8.97/0* horiz 6.54/0* (finger)
 <snip>
 event5   POINTER_AXIS     +3.219s  vert 7.42/0* horiz 0.00/0 (finger)
 event5   POINTER_AXIS 
Read: 1024 bytes, err: <nil> // <-------------- this 
text     +3.238s    vert 9.28/0* horiz -15.89/0* (finger)
 event5   POINTER_AXIS     +3.257s  vert 8.66/0* horiz -17.29/0* (finger)
 event5   POINTER_AXIS     +3.277s  vert 7.42/0* horiz -11.69/0* (finger) 
 <snip>
 event5   POINTER_AXIS     +3.491s  vert 0.00/0* horiz 0.00/0* (finger)
 event5   POINTER_MOTION   +3
Read: 1024 bytes, err: <nil>
text .980s   -0.23/ -0.90 ( -1.00/ -3.97)
 

Не могли бы вы указать мне правильный путь, пожалуйста?

1 Ответ

2 голосов
/ 06 августа 2020

Как обсуждалось в комментариях, это вовсе не проблема Go, а просто требует использования команды stdbuf в системах GNU / Linux. См. Также этот unix .stackexchange.com вопрос и ответ . Общая идея состоит в том, чтобы убедиться, что программа, которую вы запускаете с использованием exec.Command, не буферизует свой собственный вывод ненадлежащим образом.

(Программы stdbuf обычно используют LD_PRELOAD для вставки альтернативных I / Буферизация O для stdin, stdout и stderr или может быть встроена в стандартные библиотеки ОС.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...