【发布时间】:2020-03-24 08:34:41
【问题描述】:
我一直在尝试编写一个程序来记录传递给子进程的内容并实时返回控制台(将来,记录 SSH 会话,现在在 Python shell 上进行测试)
我可以毫无问题地记录 stdout 和 stderr (它显示并正确记录)但我找不到在 stdin 上做同样事情的方法? 基本上,我的标准输入将映射到子进程标准输入并写入日志文件。
这是我当前的代码:
func SSH(cmd *cobra.Command, args []string) {
logFile := fmt.Sprintf("%v@%s.log", args[0], time.Now().Format(SSHLogDateFormat))
usr, _ := user.Current()
home := usr.HomeDir
logDir := fmt.Sprintf("%s/%s/logs", home, config.ConfigDir)
if _, err := os.Stat(logDir); os.IsNotExist(err) {
err = os.Mkdir(logDir, os.FileMode(int(0700)))
if err != nil {
log.Fatalf("Failed to create %s: %s", logDir, err)
}
}
fullLogFile := fmt.Sprintf("%s/%s", logDir, logFile)
log.Infof("Started recording to %s", fullLogFile)
bash, err := exec.LookPath("bash")
if err != nil {
log.Errorf("Could not locate bash: %v", err)
}
f, err := os.Create(fullLogFile)
if err != nil {
log.Fatalf("Failed to open device logs: %s", err)
}
command := exec.Command(bash, "-c", "python")
out := io.MultiWriter(os.Stdout, f)
command.Stderr = out
command.Stdout = out
if err := command.Start(); nil != err {
log.Fatalf("Error starting program: %s, %s", command.Path, err.Error())
}
err = command.Wait()
if err != nil {
log.Fatalf("Error waiting program: %s, %s", command.Path, err.Error())
}
f.Close()
log.Infof("Finished recording to %s", fullLogFile)
}
也试过了,没有成功:
out := io.MultiWriter(os.Stdout, f)
in := io.TeeReader(os.Stdin, out)
command.Stderr = out
command.Stdout = out
command.Stdin = in
【问题讨论】:
-
golang.org/pkg/io/#TeeReader。与 MultiWriters 的原理相同,但作为一个 io.Reader 可以分配给 Stdin。
-
这不是很清楚我们如何呢?我尝试了以下事情:(添加到帖子中)但看起来它是错误的方式?
-
"TeeReader 返回一个读取器,它将从 r 读取的内容写入 w。"我不确定我可以添加什么使它更清楚。我假设你想要的是
command.Stdin = io.TeeReader(os.Stdin, f)。但由于您没有告诉我们您所说的“没有成功”是什么意思,我们只能猜测。 -
发生的情况是它看起来像覆盖了其他编写器,因为我只看到什么类型(并且只有那个被记录),stdout 被忽略了。
标签: go io subprocess pipe pipeline