【问题标题】:Redirect Selected Console Output to File将选定的控制台输出重定向到文件
【发布时间】:2013-05-31 18:04:14
【问题描述】:

我有一个小型 Java 程序,它通过 bash 脚本使用 java -jar 调用。该程序调用一个 SOAP Web 服务,我想将 SOAP 消息捕获到一个文件中,以便将来进行故障排除。我发现在独立 Java 应用程序中执行此操作的唯一方法是将其添加到我的客户端类中:

static
{
    // Output the SOAP message to the console
    System.setProperty("com.sun.xml.ws.transport.http.client.HttpTransportPipe.dump", "true");
    System.setProperty("com.sun.xml.ws.transport.http.HttpAdapter.dump", "true");
}

这会将 SOAP 消息输出到系统输出。我可以将系统重定向到一个文件,但我还有其他消息要发送到系统输出,我想在控制台上显示这些消息。可以在文件中包含这些消息,但是 SOAP 消息太多了,无法在控制台上显示。

有没有办法可以对控制台输出进行某种选择性重定向?

【问题讨论】:

  • 如果发送到控制台的其他消息是您自己的,那么您可以在它们前面加上一个特殊符号,然后通过适当的脚本过滤输出。您似乎不太可能在应用程序内执行此操作,因为 SOAP 代码将调用 System.out.print。
  • @selig 是的,这就是我最终所做的。如果您将评论添加为答案,我很乐意接受。

标签: java shell unix redirect system.out


【解决方案1】:

取决于您使用的 SOAP 库,但通常大多数 SOAP 库在将内容写入控制台时都会使用某种日志记录工具。通常,当您使用这些日志记录工具时,SOAP 库本身不会直接写入 System.out。默认情况下,日志记录工具配置为将该数据写入 System.out。因此,如果您弄清楚您正在使用哪个 SOAP 库,然后找出它使用的日志记录工具,那么您可以将日志记录配置为写入文件而不是 System.out,但仍将其他消息发送到 System.out。

我认为您正在使用使用 Java Util Logging 的 Metro。不是那么容易配置,但它可以配置多个 appender 和 loggers。我认为这会对您有所帮助:

https://metro.java.net/guide/ch02.html#logging

【讨论】:

  • 感谢您的建议。但是,我调查了 Metro 是否真的记录了 SOAP 消息,或者只是将它们写入 System.out。找不到源代码,但我能找到的所有引用都指向 System.out。为了仔细检查,我将程序更改为直接使用 java.util.Logging(副 SLFJ),但 SOAP 仍然没有记录到日志文件中。
  • 文档没有具体说明如何配置日志系统,但我确实找到了证据表明,如果您能弄清楚如何使用新的 logging.properties 文件配置日志,它将重定向它。将程序更改为使用 java.util.Logging 不会影响 SOAP 本身的日志记录配置。您必须更改 logging.properties 配置文件才能做到这一点。
  • 使用 java.util.logging 对我来说是一个有趣/令人沮丧的实验,因为我一直使用 Log4J,现在使用 Logback。所以,很有可能做到这一点,但是当我找到上述解决方案时,对我来说不值得麻烦。
【解决方案2】:

为什么不将您想要捕获的消息写入 stderr 并适当地重定向呢?您应该考虑的一点是 stdout [通常] 是缓冲的,而 stderr 不是。

您正在寻找 shell 重定向和管道。假设您使用的是标准的 shell,例如 shell、bash、csh 等。 ...

  • command >foo.txt 将重定向 stdout 到文件foo.txt。填充中的任何现有内容都将被替换。
  • command >>foo.txt 将重定向 stdout,将其附加到文件foo.txt 到foot.txt 的现有内容(如果有)。
  • foo | bar 将通过命令bar 的标准输入管道 命令foo 的stdout 的内容。

*nix 进程打开了三个标准 i/o 句柄:

  • stdin 是标准输入。它是文件句柄 0。
  • stdout 是标准输出。它是文件句柄 1。
  • stderr 是标准错误。它是文件句柄 2。

重定向和管道运算符也可以挂钩特定的文件句柄。所以...

command >foo.txt 2>&1

执行以下操作:

  1. 将标准输出重定向到文件foo.txt
  2. 将 stderr 重定向到文件句柄 1,stderr,现在打开为 foo.txt。

其他 shell 可以(并且确实)使用不同但通常相似的语法。

您还应该了解一些有用的命令:

  • tee(1).

    这将获取给定的标准输入并将其写入命令行上指定的文件以及标准输出,因此链如下:

    some-command 2>&1 | tee some-command.log.2013-05-31.txt | less
    

    运行some-command,它可能会产生大量的输出,将其stderr重定向到stdout,然后通过tee(1)进行管道传输,生成一个日志文件some-commmand.log.2013-05-31.txt并通过less(1)管道将其分页你的控制台。

  • less(1)

  • more(1)

    more 现在通常是 less(1) 的同义词。这两个都是分页器,它们缓冲输出并一次显示一个屏幕,让您可以向前和向后翻页。

  • man(1)

  • apropos(1)

    这是*nix 的在线帮助系统。要了解有关它们的更多信息,请尝试运行以下命令:

    * `man man`
    * `man apropos`
    

    获取man 和apropos 命令的手册页。您也可以尝试 man tee 或 man [your-shell-name] 来获取您正在使用的特定 shell(例如,man csh 将为您提供 csh shell 的手册页,而 man sh 将为您提供 Bourne shell( sh) 手册页和 man bash 将为您提供 bash 手册页。

本页介绍了 C 和 Bourne shell 系列的常用管道/重定向运算符:http://www.mathinfo.u-picardie.fr/asch/f/MeCS/courseware/users/help/general/unix/redirection.html

您还应该阅读相应的 O'Reilly Nutshell 书籍:

编辑备注: 正如我在下面的评论中提到的,您可以将System.Out 和System.Err 替换为您自己的PrintStream,如下所示:

PrintStream originalStdOut = System.Out ;
PrintStream newStdout = CreateNewOutputSink() ;

System.Out.flush() ;
System.Out.setOut( newStdout ) ;

invokeSome3rdPartyCode() ;

System.Out.flush() ;
System.Out.setOut( originalStdout ) ;

这将让您挂钩来自您的 3rd 方库的输出并将其重定向到您选择的数据接收器,同时不会影响您的普通输出。如果您同时钩住System.Out 和System.Err 并将它们重定向到相同 PrintStream,您将在此过程中捕获标准输出和错误输出。

【讨论】:

  • "为什么不将您想要捕获的消息写入 stderr 并适当地重定向它?"因为它是我正在使用的库中的代码,它正在写入 System.out,我无法更改它。
  • @sdoca,那么您似乎有点卡住了。但是,您可以替换 System.Out 和System.Err,通过System.setOut() 和System.setErr() 将它们设置为您自己的PrintStream。保存当前System.Out,刷新其缓冲区,将System.Out 设置为您自己的PrintStream,调用您要挂钩其输出的代码,刷新System.Out 的缓冲区并恢复原始System.Out 打印流。请参阅我修改后的答案以获取 [粗略] 示例。
  • 如果我直接调用使用 System.out 转储 SOAP 消息的代码,这可能是一个可行的解决方案。然而,这一切都隐藏在框架库的层层中。
【解决方案3】:

您似乎不太可能在应用内执行此操作,因为 SOAP 代码将调用 System.out.print。

如果您的主要目标是将输出与 SOAP 的输出分开,那么您可以在消息前添加一个特殊符号,然后通过适当的脚本过滤输出。

如果您的打印语句分布在您的代码中,您可以考虑使用 AOP(即 AspectJ)来修改它们以插入此特殊符号。就我个人而言,我通过自己的实用程序方法完成所有打印,以便在需要时可以在一个地方进行全部更改。

【讨论】:

    猜你喜欢
    • 2023-03-19
    • 2021-10-21
    • 2013-11-14
    • 2013-12-07
    • 1970-01-01
    • 2014-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多