Go语言中无法将标准输入转发至sudo子进程的问题
问题:Golang执行sudo命令无响应的原因及解决方法
最小可运行示例
package main import ( "bufio" "fmt" "io" "log" "os" "os/exec" ) func main() { //cmd := exec.Command("sudo", "tail", "-10", "/var/log/syslog") cmd := exec.Command("cat") stdin, err := cmd.StdinPipe() if err != nil { log.Fatal(err) } stdout, err := cmd.StdoutPipe() if err != nil { log.Fatal(err) } stderr, err := cmd.StderrPipe() if err != nil { log.Fatal(err) } if err := cmd.Start(); err != nil { log.Fatal(err) } ForwardStdIn(stdin) go ForwardStdOut(stdout) go ForwardStdErr(stderr) err = cmd.Wait() if err == nil { os.Exit(0) } if ee, ok := err.(*exec.ExitError); ok { fmt.Println(ee.Error()) os.Exit(ee.ExitCode()) } else { log.Fatal(err) } } func ForwardStdOut(stdout io.ReadCloser) { scanner := bufio.NewScanner(stdout) for scanner.Scan() { line := scanner.Text() _, err := fmt.Fprint(os.Stdout, line+"\n") if err != nil { log.Fatal(err) } } } func ForwardStdErr(stderr io.ReadCloser) { scanner := bufio.NewScanner(stderr) for scanner.Scan() { line := scanner.Text() _, err := fmt.Fprint(os.Stderr, line+"\n") if err != nil { log.Fatal(err) } } } func readStdin(ch chan []byte) { for { buf := make([]byte, 4096) n, err := os.Stdin.Read(buf) if n == 0 && err == io.EOF { close(ch) //fmt.Println("stdin closed #1") break } //fmt.Printf("read %v bytes\n", n) if n > 0 { ch <- buf[:n] } } } func writeStdin(stdin io.WriteCloser, ch chan []byte) { for { buf, ok := <-ch if !ok { err := stdin.Close() //fmt.Println("stdin closed #2") if err != nil { log.Fatal(err) } break } pos := 0 for pos < len(buf) { n, err := stdin.Write(buf[pos:]) if err != nil { log.Fatal(err) } //fmt.Printf("wrote %v bytes\n", n) pos += n } } } func ForwardStdIn(stdin io.WriteCloser) { ch := make(chan []byte, 2) go readStdin(ch) go writeStdin(stdin, ch) }
运行现象
- 当命令为
cat时,输入到标准输入的内容会正常输出到标准输出。 - 替换为
sudo tail -10 /var/log/syslog后,程序提示输入密码,输入密码并按下ENTER后无任何反应,既无错误信息也无输出,但调试显示密码已发送至sudo的标准输入。
额外验证
可通过以下命令在无tty的情况下正常执行sudo:
sudo tail -10 /var/log/syslog </dev/null |& cat
疑问
- 为何上述代码对
cat有效但对sudo无效? - 如何修改代码使其适配
sudo或其他使用askpass的程序?
内容的提问来源于stack exchange,提问作者nagylzs
相关产品推荐
相关产品推荐

