将stderr紧急事件重定向回go中的终端

时间:2018-12-30 00:24:10

标签: go

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

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

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

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

https://golang.org/pkg/syscall/没有给出syscall.Dup2的详细解释。我开始四处查看文件。Fd()返回以及如何使用它,但还不完全了解。

有人可以告诉我如何将stderr重定向回bash终端吗?

3 个答案:

答案 0 :(得分:2)

您必须先保存原始stderr,然后再用第一个Dup2覆盖它。 (通常,使用dup2功能关闭目标是个坏主意,因为它无法报告目标错误。)然后,您可以Dup2 那个返回int(os.Stderr.Fd())(又名2)。

答案 1 :(得分:1)

  

有人可以告诉我如何将stderr重定向回bash终端吗?

通常这是不可能的,因为可以在没有任何终端的情况下启动(或运行) Unix程序。例如,它可以由crontab(5)作业启动,或者通过某些atssh命令启动,等等。还要考虑您的程序是使用redirections还是在pipeline,或者您的程序正在服务器中运行(例如,在数据中心内部);那么很可能没有任何终端。

通常的做法是让程序的用户重定向stderr(可能重定向到终端,但是更可能重定向到某个文件)。您的用户将为此目的使用其shell(例如,运行yourprogram 2> /tmp/errorfile;阅读documentation of bash about redirections

Terminals是相当复杂的内容。您可以阅读TTY demystified页。另请参见pty(7)termios(3)。处理终端(在Unix上)的通常方法是使用ncurses库(在Go中已封装为goncurses)。

  

在程序的其他地方,我调用了syscall.Dup2(int(file.Fd()),int(os.Stderr.Fd())),它将stderr记录到外部文件中。

那真是个坏主意。您的用户希望他/她的stderr保持不变(如果需要,可以将stderr重定向到他/她的外壳中)。按照惯例,您不应在程序中弄乱standard streams(并将其留在原样)。

file descriptor是一些小的正数或零索引(进入process的文件描述符表中)。像dup2(2)这样的系统调用需要有效的文件描述符,而Go的syscall.Dup2只是将dup2(2)包装起来。

在Linux上,您可以通过查看/proc/1234/fd/目录来查询pid 1234某些进程的文件描述符表。有关更多信息,请参见proc(5)

如果您完全确定程序 在终端中运行,则可以打开/dev/tty来获取它。有关更多信息,请参见tty(4)。但是,我不建议您这样做(因为您最好将程序设计为在任何终端的外部中都可运行)。

您可能想阅读一些Linux编程书籍,例如ALP

出于记录目的,Go提供了其log软件包。另请参见syslog(3)和Go的log/syslog软件包。

PS。我不知道Windows,但我相信它也可以在没有任何终端的情况下启动程序,例如作为background process。因此,即使在Windows上,我也将尽量避免这样做(将stderr重定向到终端)。

答案 2 :(得分:0)

我不知道为什么,但是syscall.Dup2(0,int(os.Stderr.Fd()))将恐慌stderr返回到终端。

我对linux操作系统的了解很薄弱。因此,在这种情况下和Linux文档中,我不了解0的重要性。

此外,我还没有在Windows机器上尝试过这种方法,因此不确定在那里会发生什么。我希望其他人能给出更好的答案。