如何定位Java/Karaf应用收到的SIGALRM信号来源?
问题背景
我们有一个基于Karaf容器的Java应用,每5-6天会异常退出。经排查:
- 未出现JVM OOM,GC日志显示内存正常且可正常回收
- 未发生Linux系统OOM kill,dmesg及/var/log/messages中无相关日志
- JVM未损坏,未生成hs_err或core文件
通过以下strace命令追踪应用:
nohup strace -tt -e trace=signal -p 7428 -o /tmp/app.strace >/dev/null 2>&1 &
得到的strace日志显示:
[root@admin ~]# cat /tmp/app.strace 14:33:53.561413 +++ killed by SIGALRM +++
由于使用strace的-f选项会导致应用响应极慢、服务不可用,故未使用。现在需要确定:向该应用发送SIGALRM信号的程序是什么?
排查方法
1. 使用auditd追踪信号发送
auditd是系统级审计工具,对应用性能影响极小,适合生产环境:
- 安装并启动auditd服务(根据系统发行版调整命令):
# CentOS/RHEL yum install auditd -y systemctl start auditd systemctl enable auditd - 添加审计规则,仅追踪目标进程的SIGALRM信号:
注:auditctl -a exit,always -F arch=b64 -S kill -F pid=7428 -F sig=14sig=14对应SIGALRM,32位系统替换arch=b32 - 应用再次异常退出后,查看审计日志:
日志会明确显示发送信号的进程PID、PPID及进程名,直接定位发送者。ausearch -i -m kill -ts recent
2. 用sysdig轻量实时监控
sysdig是低开销的系统追踪工具,可实时捕获信号发送行为:
- 安装sysdig后,运行以下命令监控目标进程的SIGALRM:
当有SIGALRM发送到目标进程时,会实时输出发送信号的进程名和PID。sysdig -p "%proc.name %proc.pid %evt.arg.signame" evt.type=kill and evt.arg.sig=14 and proc.pid=7428
3. 优化strace参数降低性能影响
若必须使用strace,可通过缩小追踪范围减少性能损耗:
- 仅追踪SIGALRM相关信号操作,而非全信号:
若应用子进程不多,可尝试nohup strace -tt -e trace=signal -e signal=SIGALRM -p 7428 -o /tmp/app_sigalrm.strace >/dev/null 2>&1 &-ff替代-f,将每个进程日志分开写入,避免单日志过大,同时尽量缩短追踪时长。
4. 排查应用内部触发可能
SIGALRM也可能是应用自身或依赖库触发的:
- 检查Karaf及应用的定时任务配置,是否存在异常定时逻辑
- 定期用
jstack导出线程栈,分析是否有与定时、信号相关的线程异常(比如Java Timer/ScheduledExecutorService的异常,或JNI调用的原生代码发送信号)
内容的提问来源于stack exchange,提问作者Joey Sun
相关产品推荐
相关产品推荐

