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