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もはや問題はありません。

関連情報