SSHD로 전송된 신호 15의 시작자를 진단하는 방법

SSHD로 전송된 신호 15의 시작자를 진단하는 방법

최근에 sshd가 반복적으로 정지되는 문제가 발생하여 다음 점검을 수행했습니다.

  1. 에서 /var/log/messagesshd가 계속 다시 시작되는 것을 볼 수 있습니다.

    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.
    
  2. 에서 /var/log/securesshd가 때때로 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.
    
  3. 확인해 보니 sshd -t문법 오류는 없습니다

  4. 누가 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더 이상 문제가 없습니다.

관련 정보