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级别开启时拼接字符串)。