최근에 sshd가 반복적으로 정지되는 문제가 발생하여 다음 점검을 수행했습니다.
에서
/var/log/message
sshd가 계속 다시 시작되는 것을 볼 수 있습니다.Apr 23 12:05:39 host1 systemd: Stopping OpenSSH server daemon... Apr 23 12:05:39 host1 systemd: Stopped OpenSSH server daemon. Apr 23 12:05:39 host1 systemd: Starting OpenSSH server daemon... Apr 23 12:05:39 host1 systemd: Started OpenSSH server daemon.
에서
/var/log/secure
sshd가 때때로 singal 15를 수신하는 것을 발견했습니다.Apr 23 11:32:52 host1 sshd[105049]: Received signal 15; terminating. Apr 23 11:32:52 host1 sshd[111278]: Server listening on 0.0.0.0 port 36000. Apr 23 11:32:52 host1 sshd[111278]: Received signal 15; terminating. Apr 23 11:32:52 host1 sshd[111306]: Server listening on 0.0.0.0 port 36000.
확인해 보니
sshd -t
문법 오류는 없습니다누가 sshd에 신호 15를 보내고 있는지 확인하기 위해 다음을 시도했습니다. 다음에는 무엇을 시도해야 합니까?
[root@host1 /sys/kernel/debug/tracing/events/signal/signal_deliver]# echo 1 > /sys/kernel/debug/tracing/events/signal/enable [root@host1 /sys/kernel/debug/tracing/events/signal/signal_deliver]# echo "sig == 15" > /sys/kernel/debug/tracing/events/signal/filter
답변1
이를 수행하는 보편적인 Unix 방식은 없습니다. 신호 자체에는 이 정보가 전달되지 않습니다. 이는 실제 운영 체제에 따라 다릅니다. 따라서 이미 알고 있듯이 Linux에서 이 문제를 찾으려면 커널 추적을 사용해야 합니다.
귀하가 결정한 추적 지점은 최적이 아닐 수 있습니다. 신호가 발생하는 곳이 아니라 신호가 전달되는 위치를 보고 있는 것입니다! 따라서 시스템 호출의 입력(신호를 보낸 사람이 누구인지 알기 때문에)과 종료(실제로 전달되었는지 알기 때문에)를 signal_deliver
추적하는 대신 시스템 호출의 입력을 추적할 수 있습니다.kill
비록하다복잡해 보이지만 이미 이를 수행하는 도구가 있습니다.
이 bpftrace
유틸리티에는 많은 예제가 포함되어 있습니다. 귀하의 Linux 배포판은 모르지만 bpftrace
패키지를 설치했을 때 /usr/share/bpftrace/tools에는 유용한 추적 유틸리티가 많이 포함되어 있었습니다.
상황에 따라 수행해야 할 작업( 이미 수행한 경우 root
제거 sudo
):
cd /usr/share/bpftrace/tools # or whichever place these tools have been installed to
sudo ./killsnoop
당신이 원한다고 가정오직Signal 15를 시청하려면 다음과 같이 스크립트를 수정해야 합니다.
#!/usr/bin/bpftrace
/*
* signoop Trace who issues signal 15 to whom
* Base on Brendan Gregg's killsnoop, "Trace signals issued by the kill() syscall",
* USAGE: sigsnoop.bt
* Copyright 2018 Netflix, Inc.
* Copyright 2023 Marcus Müller
* Licensed under the Apache License, Version 2.0 (the "License")
*
* 07-Sep-2018 Brendan Gregg Created this.
* 23-Apr-2023 Marcus Müller made it worse :)
*/
BEGIN
{
printf("Tracing signal 15... 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
{
/* here's the relevant part: filter by sig */
if (args->sig == 15) {
@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]);
}
로 저장하고 sigsnoop.bt
누구나 실행할 수 있는 권한을 부여하고( chmod 755 sigsnoop.bt
) 루트로 실행합니다( sudo ./signsnoop.bt
).
답변2
또 다른 옵션은 다음을 사용하는 것입니다.시스템 수도꼭지. 당신이 사용할 수있는signal.send
발각.
예를 들어, 프로세스 이름으로 전송된 신호 15를 모니터링하려면 다음을 수행하십시오 sshd
.
$ stap -e 'probe begin { print("Starting monitoring...\n")}
probe signal.send {
if (sig == 15 && pid_name == "sshd")
printf ("%s(%d) sent signal 15 to %s(%d)\n", execname(), pid(), pid_name, sig_pid)
}'
출력은 다음과 유사합니다.
Starting monitoring...
bash(22405) sent signal 15 to sshd(15261)
신호를 보낸 프로세스의 명령줄도 확인할 수 있습니다.
$ stap -e 'probe begin { print("Starting monitoring...\n")}
probe signal.send {
if (sig == 15 && pid_name == "sshd")
printf ("%s(%d) (cmdline: \"%s\") sent signal 15 to %s(%d)\n", execname(), pid(), cmdline_str(), pid_name, sig_pid)
}'
Starting monitoring...
kill(20811) (cmdline: "/usr/bin/kill -15 20809") sent signal 15 to sshd(20809)
필요한 경우 더 많은 정보를 추가할 수 있습니다. 그 밖의 무엇을 참조하십시오수도꼭지 세트에서 제공합니다 systemtap
.
답변3
열정적으로 도와주신 모든 분들께 감사드립니다.
마침내 호출하는 스크립트를 찾았습니다.
service sshd restart
여러 번 반복하여 문제가 발생했습니다. 해당 진술을 주석 처리하면 sshd
더 이상 문제가 없습니다.