Linux如何找到發(fā)出 kill -9 信號的真兇?
生產(chǎn)環(huán)境遇到一個神奇的問題,某個進(jìn)程運(yùn)行一段時間后,就莫名其妙地被干掉了。初步懷疑是被操作系統(tǒng)OOM killer干掉的,但查看了dmesg日志以及系統(tǒng)內(nèi)存監(jiān)控數(shù)據(jù),發(fā)現(xiàn)內(nèi)存充足也沒有達(dá)到cgroup限制,排除了操作系統(tǒng)OMM killer干的。
應(yīng)該是被其他進(jìn)程干掉了,但系統(tǒng)里面進(jìn)程這么多,怎么知道是哪個進(jìn)程發(fā)出的kill信號呢?我們知道,sigkill(kill -9)是無法屏蔽并且不允許注冊handler的。
今天給大家介紹一個神器bpftrace,之前介紹BPF入門的文章里面已經(jīng)介紹了通過bpf攔截sys_clone系統(tǒng)調(diào)用了。原理類似,我們可以通過bpftrace攔截kill系統(tǒng)調(diào)用,從而找出殺死進(jìn)程的罪魁禍?zhǔn)住?/p>
腳本非常簡單,如下所示,主要就是在進(jìn)入系統(tǒng)調(diào)用sys_enter_kill注冊 以及 結(jié)束系統(tǒng)調(diào)用sys_exit_kill的時候獲取并打印發(fā)出信號的pid和信號編號。
- BEGIN
- {
- printf("Tracing kill() signals... Hit Ctrl-C to end.\n");
- printf("%-9s %-6s %-16s %-4s %-6s %s\n", "TIME", "PID", "COMM", "SIG",
- "TPID", "RESULT");
- }
- tracepoint:syscalls:sys_enter_kill
- {
- @tpid[tid] = args->pid;
- @tsig[tid] = args->sig;
- }
- tracepoint:syscalls:sys_exit_kill
- /@tpid[tid]/
- {
- time("%H:%M:%S ");
- printf("%-6d %-16s %-4d %-6d %d\n", pid, comm, @tsig[tid], @tpid[tid],
- args->ret);
- delete(@tpid[tid]);
- delete(@tsig[tid]);
- }
我們可以先啟動一個sleep的Demo測試
- # sleep 444
執(zhí)行上面的腳本后,通過 ”kill -9 “殺死上面啟動sleep 任務(wù),可以腳本輸出如下:
- TIME PID COMM SIG TPID RESULT
- 11:38:43 2837583 bash 9 2837548 0
其中,TIME代表執(zhí)行時間,PID代表發(fā)出信號的進(jìn)程ID,COMM代表發(fā)出信號進(jìn)程命令行,由于是在bash環(huán)境中執(zhí)行的kill -9 所以這里顯示bash,SIG代表信號編號,本例中是kill -9 信號,TPID是sleep任務(wù)的線程ID,RESULT代表執(zhí)行結(jié)果,0代表成功。”殺手“和”受害者“都已經(jīng)成功顯示。
最終通過上面的腳本找到了系統(tǒng)上面一個自動清理程序,由于使用了通配符導(dǎo)致誤殺的情況。