【问题标题】:Copy STDOUT to file without stopping it showing onscreen将 STDOUT 复制到文件而不停止它在屏幕上显示
【发布时间】:2009-08-31 09:46:37
【问题描述】:

我正在制作的程序旨在无人值守运行,因此我已将 stdout 和 stderr 流重定向到日志文件。虽然这没有任何问题,但我仍在制作和调试软件,我希望它也能在屏幕上显示。这可能吗?

重定向我使用过的流

System.setErr(logWriter);
System.setOut(logWriter);

谢谢。

【问题讨论】:

    标签: java stdout stderr


    【解决方案1】:

    是的。日志框架(即 log4j)是最好的,isDebugMode 在开发环境中很方便但是如果你真的需要“tee”你的标准输出,你可以喜欢。

    import java.io.PrintStream;
    import java.io.File;
    public class TeeStream extends PrintStream {
        PrintStream out;
        public TeeStream(PrintStream out1, PrintStream out2) {
            super(out1);
            this.out = out2;
        }
        public void write(byte buf[], int off, int len) {
            try {
                super.write(buf, off, len);
                out.write(buf, off, len);
            } catch (Exception e) {
            }
        }
        public void flush() {
            super.flush();
            out.flush();
        }
    }
    

    http://www.exampledepot.com/egs/java.lang/Redirect.html

    // import java.io.FileOutputStream;
    String dateString = new SimpleDateFormat("yyyyMMdd").format(new Date());
    File logFile = new File("mylogfile_" + dateString +".log");
    PrintStream logOut = new PrintStream(new FileOutputStream(logFile, true));
    
    PrintStream teeStdOut = new TeeStream(System.out, logOut);
    PrintStream teeStdErr = new TeeStream(System.err, logOut);
    
    System.setOut(teeStdOut);
    System.setErr(teeStdErr);
    

    您很快就会发现LOG.somelevel(msg)System.out.println(msg) 更易于管理。当事情运行良好时提高日志级别并在不部署调试版本的情况下降低日志级别是很棒的。

    【讨论】:

      【解决方案2】:

      也许有点粗糙,但你可以试试这个:

      private static final isDebugMode = true;
      
      ...
      
      if (!isDebugMode) {
        System.setErr(logWriter);
        System.setOut(logWriter);
      } 
      

      或者,您可以编写自己的 PrintStream 实现,该实现同时写入您的日志文件和屏幕。听起来你不需要这种行为,除非在开发中,所以后者虽然实际上对你的问题的更准确的答案可能不是你真正想要的。

      【讨论】:

      • 谢谢,一个简单的解决方案,不知道为什么我没有想到它:)
      【解决方案3】:

      如果您使用的是类 Unix 平台(Windows 除外),您可以使用 tee 程序:

      java myprogram | tee output
      

      这会将标准输出以及名为output的文件写入控制台。

      【讨论】:

        【解决方案4】:

        不,根据您的设置,这是不可能的。可能的解决方案:

        • 使用一些软件来监控日志文件。在 Linux/Unix 上,less 有一个“跟随”模式 (Shift-F),用于跟踪日志文件。其他系统应该有类似的代码。这具有在调试和生产中使用相同设置的优势。
        • 您确实应该考虑使用适当的日志记录框架(java.util.logging、Log4j 或类似的)。这使您的日志记录设置更加灵活。在众多优势中,您可以灵活配置(无需更改代码)日志应该放在哪里。

        【讨论】:

        • +1 用于日志框架。这将允许文件、标准输出、套接字、数据库流等。您还可以调低或调高日志输出。
        • 我研究过使用日志框架,虽然我可能会考虑稍后实现它,但我正在做的事情似乎有点多。
        【解决方案5】:

        如果您使用的是 UNIX,您可以使用 tail -f logfile 查看写入日志文件的行

        【讨论】:

          【解决方案6】:

          如果你不想要一个合适的日志框架

          标准的 Unix 方式是重定向输出流

          ie 运行程序 exex 作为 exe > 日志 将标准输出重定向到日志 但 可执行程序 它自己会将输出留给控制台。

          如果您想在程序中执行此操作,您需要一个变量来测试,如果不测试则只重定向流

          【讨论】:

            【解决方案7】:

            在 Linux 和 Windows(安装了 cygwin)上,我总是使用 log4j 记录到文件,然后使用“tail”来显示它。默认情况下,tail -f(和 less -F)每秒更新一次,我觉得这太慢了。此外,通常有几个有趣的日志文件值得一看,其中一些包含日期作为其名称的一部分。这是我在我的一个系统上使用的命令:

            ( cd /var/log/myapp/; tail -Fq --lines=0 -s 0.05 $(find . -type f -name "*$(date '+%Y-%m-%d').log" ) ) &
            

            这会同时跟踪 /var/log/myapp/ 下的每个日志文件,文件名中包含今天的日期。 log4j 滚动日志文件非常方便。而 -s 0.05 意味着在检查新输出之间仅暂停 0.05 秒。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-12-10
              • 1970-01-01
              • 1970-01-01
              • 2018-08-22
              • 1970-01-01
              相关资源
              最近更新 更多