现象描述
最近在维护一个线上服务时,发现进程突然退出,日志显示收到了SIGTERM信号并以退出码0正常终止。这让我很困惑,因为系统资源监控显示内存充足,也没有人为干预操作。
SIGTERM触发机制解析
在Linux/BusyBox环境中,SIGTERM信号的发送通常来自以下几个场景:
// 示例:查看信号处理函数
#include <signal.h>
#include <stdio.h>
void handler(int sig) {
printf("Received signal %d\n", sig);
}
int main() {
signal(SIGTERM, handler);
while(1);
return 0;
}
常见触发场景
1. 系统关机/重启流程
在init系统(如systemd/sysvinit)执行关机时,会先发送SIGTERM给所有进程
# 模拟关机信号发送
kill -TERM `pidof your_process`
2. 容器环境调度
在Kubernetes/Docker环境中,Pod终止或资源限制触发时:
# Kubernetes preStop hook示例
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 30"]
3. 进程监控工具干预
如supervisor、monit等工具在配置超时后可能发送SIGTERM
诊断方法
通过审计日志追踪信号来源:
# 方法1:查看系统日志
journalctl -k | grep -i sigterm
# 方法2:使用strace跟踪
strace -p <PID> -e trace=signal
防御性编程建议
正确处理信号避免数据损坏:
// 改进的信号处理示例
void graceful_shutdown(int sig) {
// 保存状态
save_work_state();
// 关闭资源
close_db_connections();
// 退出进程
_exit(0);
}
int main() {
struct sigaction act;
act.sa_handler = graceful_shutdown;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
sigaction(SIGTERM, &act, NULL);
// ... 主逻辑
}
容器环境特殊处理
对于Docker/K8s环境,需要正确处理preStop和terminationGracePeriodSeconds:
# Docker示例
docker run --name test --stop-signal SIGTERM your_image
# K8s部署示例
apiVersion: v1
kind: Pod
spec:
terminationGracePeriodSeconds: 60
监控与告警配置
建议对非预期的SIGTERM建立监控:
# Prometheus告警规则示例
- alert: UnexpectedProcessTermination
expr: increase(process_terminations_total{signal="terminated"}[5m]) > 0
for: 1m
labels:
severity: warning
annotations:
summary: "Process terminated by SIGTERM"