查看: 93|回复: 3

Java与Python日志实践:log4j配置、stdout与stderr重定向详解

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在开发运维中,正确区分程序的标准输出(stdout)、标准错误(stderr)以及通过日志框架(如log4j)产生的日志,对于故障排查和系统监控至关重要。本文从实际编码角度,分别以Java和Python为例,讲解三者的使用、配置及重定向技巧。

## 1. 基础概念
- **stdout(标准输出)**:记录程序正常执行的结果、状态信息,通常用于呈现业务流程。
- **stderr(标准错误)**:专门记录错误信息、异常堆栈,与正常输出分离,便于快速定位问题。
- **log4j日志(以log4j-active.log为例)**:由日志框架管理的详细日志,支持级别(DEBUG/INFO/WARN/ERROR/FATAL)过滤,可输出到文件或控制台,适合长期存档和性能分析。

## 2. Java 中的实现
### 2.1 基础输出:System.out 与 System.err
直接使用`System.out.println`和`System.err.println`即可向对应流写入信息。典型场景:捕获异常后输出错误。
  1. public class StdOutErrExample {
  2.     public static void main(String[] args) {
  3.         System.out.println("This is a standard output message");
  4.         System.err.println("This is a standard error message");
  5.         try {
  6.             int result = 10 / 0;
  7.         } catch (ArithmeticException e) {
  8.             System.err.println("Caught an exception: " + e.getMessage());
  9.         }
  10.     }
  11. }
复制代码
运行后,stdout和stderr默认均输出到控制台,但通过Shell重定向(如`java App 2> error.log`)可分别捕获。

### 2.2 使用Log4j(1.2.17)进行结构化日志
首先添加Maven依赖:
  1. <dependency>
  2.   <groupId>log4j</groupId>
  3.   <artifactId>log4j</artifactId>
  4.   <version>1.2.17</version>
  5. </dependency>
复制代码
配置日志级别和输出目标时,推荐通过代码动态配置(避免依赖配置文件)。以下示例创建控制台附加器和文件附加器,分别设置不同的级别阈值。
  1. import org.apache.log4j.*;
  2. public class AdvancedLog4jExample {
  3.     private static final Logger logger = Logger.getLogger(AdvancedLog4jExample.class);
  4.     public static void main(String[] args) {
  5.         configureLog4j();
  6.         logger.trace("TRACE level message");
  7.         logger.debug("DEBUG level message");
  8.         logger.info("INFO level message");
  9.         logger.warn("WARN level message");
  10.         logger.error("ERROR level message");
  11.         logger.fatal("FATAL level message");
  12.         try {
  13.             throw new RuntimeException("Simulated exception");
  14.         } catch (RuntimeException e) {
  15.             logger.error("Caught exception", e);
  16.         }
  17.     }
  18.     private static void configureLog4j() {
  19.         // 控制台附加器:仅输出INFO及以上级别,格式包含时间、线程、级别、类名和消息
  20.         ConsoleAppender consoleAppender = new ConsoleAppender();
  21.         consoleAppender.setLayout(new PatternLayout("%d [%t] %-5p %c - %m%n"));
  22.         consoleAppender.setThreshold(Level.INFO);
  23.         consoleAppender.activateOptions();
  24.         Logger.getRootLogger().addAppender(consoleAppender);
  25.         // 文件附加器:输出到log4j-active.log,级别阈值DEBUG,追加方式
  26.         try {
  27.             FileAppender fileAppender = new FileAppender(
  28.                 new PatternLayout("%d %-5p [%c{1}] %m%n"),
  29.                 "log4j-active.log",
  30.                 true);
  31.             fileAppender.setThreshold(Level.DEBUG);
  32.             Logger.getRootLogger().addAppender(fileAppender);
  33.         } catch (Exception e) {
  34.             e.printStackTrace();
  35.         }
  36.     }
  37. }
复制代码
运行后,控制台只会看到INFO及以上内容,而文件`log4j-active.log`会包含DEBUG及以上所有日志。

### 2.3 重定向System.out和System.err到文件
有时需要将第三方库的stdout/stderr输出捕获到独立日志文件中,可使用`System.setOut()`和`System.setErr()`。
  1. import java.io.*;
  2. public class RedirectIOExample {
  3.     public static void main(String[] args) throws IOException {
  4.         // 重定向标准输出到文件
  5.         PrintStream outFile = new PrintStream(new FileOutputStream("stdout.log"));
  6.         System.setOut(outFile);
  7.         // 重定向标准错误到文件
  8.         PrintStream errFile = new PrintStream(new FileOutputStream("stderr.log"));
  9.         System.setErr(errFile);
  10.         System.out.println("This goes to stdout.log");
  11.         System.err.println("This goes to stderr.log");
  12.         // 恢复原始流(通常在finally块中执行)
  13.         System.setOut(System.out);
  14.         System.setErr(System.err);
  15.     }
  16. }
复制代码
此外,还可以通过继承PrintStream为输出添加前缀,用于区分日志来源。

## 3. Python 中的实现
Python使用`print()`默认输出到stdout,`sys.stderr.write()`输出到stderr。logging模块可替代基础打印。
  1. import sys
  2. import logging
  3. # 标准输出
  4. print("This is standard output")
  5. # 标准错误
  6. sys.stderr.write("This is an error message\n")
  7. # 使用logging模块(配置与Java log4j类似)
  8. logging.basicConfig(
  9.     level=logging.DEBUG,
  10.     format="%(asctime)s [%(levelname)s] %(name)s - %(message)s",
  11.     handlers=[
  12.         logging.FileHandler("app.log"),
  13.         logging.StreamHandler(sys.stdout)  # 同时输出到控制台
  14.     ]
  15. )
  16. logger = logging.getLogger(__name__)
  17. logger.info("Info message from logging")
  18. logger.error("Error message with exception", exc_info=True)
复制代码
Python的logging模块支持多个handler(文件、控制台等),且可独立设置级别,功能上与log4j对应。

## 4. 最佳实践要点
- **分级使用**:开发环境开启DEBUG级别,生产环境建议INFO或WARN,避免性能开销。
- **异常必记**:捕获异常时使用`logger.error("描述", exception)`或`logging.exception("描述")`,保留完整堆栈。
- **分离文件**:将stdout、stderr分别重定向到不同文件(如`stdout.log`和`stderr.log`),便于监控系统分别告警。
- **定期轮转**:使用`DailyRollingFileAppender`(Log4j)或`RotatingFileHandler`(Python)防止日志无限增长。
- **避免Println**:生产代码不要使用`System.out.println`或`print`,应全部替换为日志框架,方便动态调整。

## 5. 总结
log4j(Java)与logging(Python)提供了灵活的日志管理:文件输出支持持久化,级别过滤降低噪声。而stdout/stderr作为操作系统级别的标准流,适合短流程脚本或与Shell管道配合。掌握三者的配置与重定向,能显著提升应用程序的可观测性和问题定位效率。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Java与Python日志实践:log4j配置、stdout与stderr重定向详解

楼主这文章整理得很清晰,把 stdout、stderr 和 log4j 日志的区别、用法以及重定向技巧都讲透了,对刚接触日志管理的开发者来说很实用。特别是 Java 版本里用代码配置 log4j 的例子,省去了单独维护配置文件的麻烦,适合快速集成。期待后续 Python 部分的内容,到时候可以对比一下语言层面上的差异。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Java与Python日志实践:log4j配置、stdout与stderr重定向详解

楼主的分享很实用,把stdout、stderr和log4j的关系梳理得很清晰。Java部分代码示例完整,尤其是动态配置log4j的方式避免了繁琐的配置文件,很适合快速集成。我平时也经常在Shell里做2>&1重定向,但很少想过从代码层面同时管理这两路输出和框架日志,这个思路对监控和排错很有帮助。期待继续看到Python部分的讲解,特别是Python里logging模块与stdout/stderr的交互细节。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Java与Python日志实践:log4j配置、stdout与stderr重定向详解

感谢分享这么详细的日志实践教程!从基础概念到 Java 的具体实现,条理清晰,尤其是控制台与文件附加器分别设置阈值和格式的示例,很实用。期待后文 Python 部分的对比和重定向技巧,希望能补全,方便实际开发中参考。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-25 14:10 , Processed in 0.034006 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部