猿问

将 stderr 恐慌重定向回终端

我正在尝试使用以下代码将恐慌/标准错误重定向回 bash 终端:

    if err := syscall.Dup2(-1,int(os.Stderr.Fd())); err != nil {
      log.Fatalf("Failed to redirect stderr to bash: %v",err)
    }

但是错误给了我一个“错误的文件描述符”,可能是因为-1我在第一个参数中使用了。我选择这个值是-1因为我发现它int(file.(*os.File).Fd())返回了一个-1when file.Close()has been called。

至于我想做什么。在我的程序的其他地方,我调用了一个syscall.Dup2(int(file.Fd()), int(os.Stderr.Fd())),它将 stderr 记录到一个外部文件中。但有时我希望 stderr 指向 bash 终端。

https://golang.org/pkg/syscall/没有给出 syscall.Dup2 的详细解释。我开始研究 file.Fd() 返回什么以及它是如何使用的,但也没有完全理解。

谁能告诉我如何将 stderr 重定向回 bash 终端?


MYYA
浏览 161回答 3
3回答

收到一只叮咚

在用第一个Dup2. (一般来说,使用dup2关闭目标的功能是个坏主意,因为它不能从那里报告错误。)然后你可以把Dup2 它返回到int(os.Stderr.Fd())(aka 2)。

红糖糍粑

谁能告诉我如何将 stderr 重定向回 bash 终端?一般来说,这是不可能的,因为 Unix 程序可以在没有任何终端的情况下启动(或运行)。例如,它可以由crontab(5)作业启动,或通过一些at或ssh命令等启动。还可以考虑您的程序正在使用重定向或在管道中运行,或者您的程序正在服务器中运行(例如在一个数据中心); 那么它很可能没有任何终端。通常的做法是您的程序的用户可能会重定向stderr(并且可能不会重定向到终端,但更有可能重定向到某个文件)。您的用户将为此目的使用其外壳yourprogram 2> /tmp/errorfile(例如运行;阅读关于重定向的文档bash)终端是相当复杂的东西。您可以阅读TTY demystified页面。另请参见pty(7)和termios(3)。处理终端(在 Unix 上)的常用方法是使用ncurses库(在 Go 中已包装为goncurses)。在我程序的其他地方,我调用了 syscall.Dup2(int(file.Fd()), int(os.Stderr.Fd())),它将 stderr 记录到外部文件。这真是个坏主意。您的用户希望他/她的stderr保持不变(stderr如果需要,会在他/她的 shell 中重定向)。按照惯例,您不应该在程序中弄乱标准流(让它们保持原样)。文件描述符是一些小的正或零索引(进入进程的文件描述符表)。像dup2(2)这样的系统调用需要有效的文件描述符,而 Gosyscall.Dup2只是包装dup2(2)。在Linux上,可以通过查看目录来查询pid为1234的某个进程的文件描述符表/proc/1234/fd/。有关更多信息,请参见proc(5)。如果您绝对确定您的程序正在终端中运行,您可能会打开/dev/tty它。但是,我不建议这样做(因为您最好将程序设计为可在任何终端之外运行)。出于日志记录的目的,Go 提供了它的日志包。另请参阅syslog(3)和log/syslogGo 的包。附言。我不知道 Windows,但我相信它也可以在没有任何终端的情况下启动程序,例如作为后台进程。因此,即使在 Windows 上,我也会尽量避免这样做(将 stderr 重定向到终端)。

明月笑刀无情

我不知道为什么,但syscall.Dup2(0,int(os.Stderr.Fd()))将 panic stderr 返回到终端。我对linux操作系统的了解很薄弱。0所以我不明白在这种情况下和 linux 文档中 的重要性。另外,我还没有在 Windows 机器上尝试过这种方法,所以不确定那里会发生什么。我希望其他人能给出更好的答案。
随时随地看视频慕课网APP

相关分类

Go
我要回答