Java程序在Ubuntu上的日志管理技巧
Java生态中有多种日志框架可供选择,需根据项目需求选取:
<?xml version="1.0" encoding="UTF-8"?> <Configuration status="WARN"> <Appenders> <!-- 控制台输出 --> <Console name="Console" target="SYSTEM_OUT"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/> </Console> <!-- 文件输出(带滚动策略) --> <RollingFile name="File" fileName="/var/log/myapp/app.log" filePattern="/var/log/myapp/app-%d{yyyy-MM-dd}-%i.log.gz"> <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/> <Policies> <TimeBasedTriggeringPolicy interval="1" modulate="true"/> <!-- 按天滚动 --> <SizeBasedTriggeringPolicy size="250 MB"/> <!-- 按大小滚动 --> </Policies> <DefaultRolloverStrategy max="7"/> <!-- 保留7个归档文件 --> </RollingFile> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="Console"/> <AppenderRef ref="File"/> </Root> <!-- 特定类调整日志级别(如调试某类) --> <Logger name="com.example.MyClass" level="debug" additivity="false"/> </Loggers> </Configuration> <configuration> <Appenders> <!-- 控制台输出 --> <Console name="STDOUT" target="SYSTEM_OUT"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </Console> <!-- 文件输出(带滚动策略) --> <RollingFile name="FILE" fileName="/var/log/myapp/app.log" filePattern="/var/log/myapp/app-%d{yyyy-MM-dd}.%i.log.gz"> <encoder> <pattern>%d{yyyy-MM-dd HH:mm:ss} %-5level %logger{36} - %msg%n</pattern> </encoder> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>/var/log/myapp/app-%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern> <maxHistory>30</maxHistory> <!-- 保留30天日志 --> </rollingPolicy> <triggeringPolicy class="ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy"> <maxFileSize>250MB</maxFileSize> <!-- 单个文件最大250MB --> </triggeringPolicy> </RollingFile> </Appenders> <Loggers> <Root level="info"> <AppenderRef ref="STDOUT"/> <AppenderRef ref="FILE"/> </Root> </Loggers> </configuration> # 全局日志级别 .level=INFO # 控制台Handler handlers=java.util.logging.ConsoleHandler java.util.logging.ConsoleHandler.level=INFO java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter # 文件Handler java.util.logging.FileHandler.level=INFO java.util.logging.FileHandler.pattern=/var/log/myapp/app.log java.util.logging.FileHandler.limit=50000 # 50MB java.util.logging.FileHandler.count=5 # 保留5个文件 java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter 注意:配置文件需放置在项目资源目录(如src/main/resources),启动时加载(如Log4j 2会自动加载,JUL需通过-Djava.util.logging.config.file指定路径)。
日志文件过大易导致磁盘空间耗尽,需通过轮转策略分割日志:
# 创建myapp日志轮转配置 sudo nano /etc/logrotate.d/myapp 添加以下内容:
/var/log/myapp/*.log { daily # 每天轮转 rotate 7 # 保留7个归档文件 compress # 压缩旧日志(.gz格式) missingok # 日志文件不存在时不报错 notifempty # 日志为空时不轮转 create 640 root adm # 新日志文件权限 sharedscripts # 所有日志轮转完成后执行脚本 postrotate systemctl restart myapp.service # 重启应用(可选,确保应用重新写入新日志) endscript } 测试配置:
sudo logrotate -f /etc/logrotate.d/myapp # 强制立即轮转 Log4j 2和Logback均支持内置轮转(如上述配置中的RollingFile Appender),无需额外工具,更贴合应用需求。
若Java应用通过Systemd服务运行(如myapp.service),可使用journalctl命令管理日志:
journalctl -u myapp.service # 查看指定服务的日志 journalctl -u myapp.service -f # 实时跟踪日志 journalctl -u myapp.service --since "2025-10-20" --until "2025-10-22" # 按时间范围查看 编辑Systemd journal配置:
sudo nano /etc/systemd/journald.conf 修改以下参数(取消注释并调整值):
SystemMaxUse=500M # 日志总大小上限 SystemKeepFree=100M # 磁盘剩余空间下限 SystemMaxFileSize=50M # 单个日志文件大小上限 SystemMaxFiles=5 # 保留的日志文件数量 重启journald服务:
sudo systemctl restart systemd-journald journalctl -u myapp.service > /var/log/myapp/journal.log Systemd journal的优势在于索引化存储,支持快速搜索和过滤,适合集成到系统级日志管理。
Ubuntu提供的命令行工具可快速查看和分析日志:
tail -f /var/log/myapp/app.log # 实时输出日志新增内容 grep "ERROR" /var/log/myapp/app.log # 查找包含"ERROR"的行 grep -i "exception" /var/log/myapp/app.log # 忽略大小写查找"exception" less /var/log/myapp/app.log # 按页查看,支持上下翻页(空格键)、搜索(/关键字) head -n 50 /var/log/myapp/app.log # 查看前50行 tail -n 50 /var/log/myapp/app.log # 查看后50行 这些工具适合快速排查问题,无需安装额外软件。
对于分布式系统或多节点应用,可使用ELK Stack(Elasticsearch + Logstash + Kibana)实现集中化日志管理:
# 安装Elasticsearch wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add - echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list sudo apt-get update && sudo apt-get install elasticsearch # 安装Logstash sudo apt-get install logstash # 安装Kibana sudo apt-get install kibana # 启动服务 sudo systemctl start elasticsearch sudo systemctl start logstash sudo systemctl start kibana 创建/etc/logstash/conf.d/java.conf:
input { file { path => "/var/log/myapp/app.log" start_position => "beginning" sincedb_path => "/dev/null" # 测试时使用,正式环境需删除 } } filter { grok { match => { "message" => "%{TIMESTAMP_ISO8601:timestamp} %{LOGLEVEL:loglevel} %{JAVACLASS:class} - %{GREEDYDATA:logmessage}" } } date { match => [ "timestamp", "ISO8601" ] } } output { elasticsearch { hosts => ["localhost:9200"] index => "myapp-logs-%{+YYYY.MM.dd}" } stdout { codec => rubydebug } # 测试时输出到控制台 } 浏览器访问http://<Ubuntu-IP>:5601,创建索引模式(如myapp-logs-*),即可通过Kibana的Dashboard进行日志搜索、分析和可视化。
ELK的优势在于实时性、可扩展性和强大的分析能力,适合大型应用或需要深度日志分析的场景。
DEBUG,记录详细信息(如方法调用、变量值),便于调试;INFO或WARN,仅记录关键信息(如应用启动、错误),减少日志量和IO开销。Log4j 2和Logback均支持异步日志记录(如Log4j 2的AsyncAppender、Logback的AsyncAppender),将日志写入操作放入单独线程,避免阻塞主线程,提升应用性能。
logger.debug("Value: {}", value),仅在DEBUG级别开启时拼接字符串)。