当标准输入(stdin)被重定向到其他地方时,Go程序能否从键盘读取输入?

huangapple go评论114阅读模式
英文:

Can a Go program read from the keyboard when stdin is something else?

问题

我有一个通过管道接收输入的Go进程。

> tail -f something.foo | go run myprog.go

由于stdin是管道的输出,我找不到一种方法在myprog.go中读取键盘输入。这可能吗?

我考虑在myprog.go内部执行tail命令,但我希望在myprog.go崩溃并无法终止另一个进程时避免创建另一个进程。

英文:

I have a Go process that accepts input via pipe.

> tail -f something.foo | go run myprog.go

Since stdin is the output of the pipe, I can't find a way to read keyboard input in myprog.go. Is this possible?

I considered executing the tail command inside of myprog.go, but I want to avoid creating another process in the event myprog.go crashes and fails to terminate the other one.

答案1

得分: 5

在Linux(以及POSIX通用)上,您可以打开/dev/tty以获取您的进程的控制终端的输入。

  1. func readStdin() {
  2. buf := make([]byte, 1024)
  3. for {
  4. n, err := os.Stdin.Read(buf)
  5. if err != nil && err != io.EOF {
  6. log.Fatal(err)
  7. }
  8. fmt.Print("FROM STDIN:", string(buf[:n]))
  9. if err == io.EOF {
  10. return
  11. }
  12. }
  13. }
  14. func main() {
  15. go readStdin()
  16. buf := make([]byte, 1024)
  17. tty, err := os.Open("/dev/tty")
  18. if err != nil {
  19. log.Fatal(err)
  20. }
  21. defer tty.Close()
  22. for {
  23. n, err := tty.Read(buf)
  24. if err != nil && err != io.EOF {
  25. log.Fatal(err)
  26. }
  27. fmt.Print("FROM TTY:", string(buf[:n]))
  28. if err == io.EOF {
  29. return
  30. }
  31. }
  32. }

可以输出:

  1. $ echo HELLO | ./tty_reader
  2. FROM STDIN:HELLO
  3. typing on my keyboard
  4. FROM TTY:typing on my keyboard
英文:

On linux (and POSIX in general), you can open /dev/tty to get the input to the controlling tty for your process.

  1. func readStdin() {
  2. buf := make([]byte, 1024)
  3. for {
  4. n, err := os.Stdin.Read(buf)
  5. if err != nil && err != io.EOF {
  6. log.Fatal(err)
  7. }
  8. fmt.Print("FROM STDIN:", string(buf[:n]))
  9. if err == io.EOF {
  10. return
  11. }
  12. }
  13. }
  14. func main() {
  15. go readStdin()
  16. buf := make([]byte, 1024)
  17. tty, err := os.Open("/dev/tty")
  18. if err != nil {
  19. log.Fatal(err)
  20. }
  21. defer tty.Close()
  22. for {
  23. n, err := tty.Read(buf)
  24. if err != nil && err != io.EOF {
  25. log.Fatal(err)
  26. }
  27. fmt.Print("FROM TTY:", string(buf[:n]))
  28. if err == io.EOF {
  29. return
  30. }
  31. }
  32. }

Which can output:

  1. $ echo HELLO | ./tty_reader
  2. FROM STDIN:HELLO
  3. typing on my keyboard
  4. FROM TTY:typing on my keyboard

答案2

得分: -1

你可以使用shell来创建一个管道,以便为程序提供输入,同时保持标准输入(stdin)可用于其他操作。一个示例是:

  1. go run myprog.go <(tail -f something.foo)

Shell会执行tail命令,并将其标准输出重定向到一个新的命名管道(fifo)。你的程序将接收到该命名管道作为第一个参数,指向/proc/self/fd/1234567

英文:

You can use the shell to create a pipe for you to feed input to your program while leaving stdin free for other things. Something to the sound of

  1. go run myprog.go &lt;(tail -f something.foo)

The shell will execute tail and redirect it's stdout to a new fifo. Your program receives the fifo as first argument, pointing to /proc/self/fd/1234567

huangapple
  • 本文由 发表于 2015年4月3日 01:25:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/29418868.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定