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

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

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以获取您的进程的控制终端的输入。

func readStdin() {
    buf := make([]byte, 1024)
    for {
        n, err := os.Stdin.Read(buf)
        if err != nil && err != io.EOF {
            log.Fatal(err)
        }
        fmt.Print("FROM STDIN:", string(buf[:n]))
        if err == io.EOF {
            return
        }
    }
}

func main() {
    go readStdin()

    buf := make([]byte, 1024)
    tty, err := os.Open("/dev/tty")
    if err != nil {
        log.Fatal(err)
    }
    defer tty.Close()
    for {
        n, err := tty.Read(buf)
        if err != nil && err != io.EOF {
            log.Fatal(err)
        }
        fmt.Print("FROM TTY:", string(buf[:n]))
        if err == io.EOF {
            return
        }
    }
}

可以输出:

$ echo HELLO | ./tty_reader
FROM STDIN:HELLO
typing on my keyboard
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.

func readStdin() {
	buf := make([]byte, 1024)
	for {
		n, err := os.Stdin.Read(buf)
		if err != nil && err != io.EOF {
			log.Fatal(err)
		}
		fmt.Print("FROM STDIN:", string(buf[:n]))
		if err == io.EOF {
			return
		}
	}
}

func main() {
	go readStdin()

	buf := make([]byte, 1024)
	tty, err := os.Open("/dev/tty")
	if err != nil {
		log.Fatal(err)
	}
	defer tty.Close()
	for {
		n, err := tty.Read(buf)
		if err != nil && err != io.EOF {
			log.Fatal(err)
		}
		fmt.Print("FROM TTY:", string(buf[:n]))
		if err == io.EOF {
			return
		}
	}
}

Which can output:

$ echo HELLO | ./tty_reader
FROM STDIN:HELLO
typing on my keyboard
FROM TTY:typing on my keyboard

答案2

得分: -1

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

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

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:

确定