审计日志

审计日志设置简单,但不提供对监控哪些进程和信号的细粒度控制;一切都包括在内。
因此日志可能会变得非常嘈杂,因此建议在确定进程后立即禁用监控。
步骤是:

  1. 配置auditd 以监视信号。
    这可以在运行时或者通过 auditd 配置文件 (/etc/audit/audit.rules) 完成。
    由于添加的日志输出相当嘈杂(它记录所有信号甚至 kill -0 例如:检查进程是否处于活动状态)并且进行更改是为了调试单个问题,通常最好在运行。
    我们可以使用以下命令执行此操作:
auditctl -a exit,always -F arch=b64 -S kill -k audit_kill
  1. 等待mysqld被信号杀死/关闭。

  2. 再次停止auditd日志信号调用,最简单的就是重启(如果在配置文件中添加了规则,则需要先删除规则):

# service auditd restart

日志文件(通常是 /var/log/audit.log )现在应该有一个类似于:

type=SYSCALL msg=audit(1450214919.813:148): arch=c000003e syscall=62 success=yes exit=0 a0=f60 a1=9 a2=7f736e706980 a3=0 items=0 ppid=3649 pid=3997 auid=500 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts3 ses=1 comm="mykill" exe="/opt/bin/mykill" subj=user_u:system_r:unconfined_t:s0 key="audit_kill"
type=OBJ_PID msg=audit(1450214919.813:148): opid=3936 oauid=500 ouid=102 oses=1 obj=user_u:system_r:mysqld_t:s0 ocomm="mysqld"

重要的信息:

General:

msg=audit(1450214919.813:148) :事件的时间戳。
这是在纪元(自 1970 年 1 月 1 日午夜 UTC 开始的时间)。
你可以例如使用 MySQL 中的 FROM_UNIXTIME() 函数将其转换为正常日期:

mysql> SELECT FROM_UNIXTIME(1450214919);
+---------------------------+
| FROM_UNIXTIME(1450214919) |
+---------------------------+
| 2015-12-16 08:28:39       |
+---------------------------+
1 row in set (0.05 sec)

type=SYSCALL

有关系统调用触发器的信息。

syscall=62 :表示这是一个信号(杀死):

# ausyscall 62
kill

a1=9 :表示信号为 SIGKILL(对于 SIGTERM 信号,值为 15)。

comm="mykill" exe="/opt/bin/mykill" :是发送信号的进程,这是我们感兴趣的。

key="audit_kill" :是来自 auditctl 命令的“-k audit_kill”选项。
它只是告诉事件是由我们添加的规则触发的。

type=OBJ_PID

有关系统调用目标的信息。

opid=3936 :是接收信号的进程的进程 ID(如我们在 top 或者 ps 输出中看到的那样)。

ouid=102 :执行进程的用户的用户 ID(如 /etc/passwd 中的 ID)。

ocomm="mysqld" :进程的名称。

因此,我们需要查找 type=SYSCALL 且 a1=9 和 key="audit_kill" 的事件,其中以下对象具有 ocomm="mysqld"。

欢迎来到之路教程(on itroad-com)

systemtap

systemtap 需要一个脚本来指定应该监控什么以及应该用可用信息做什么。
这使其使用起来更加复杂,但也提供了更大的灵活性。
将监视 SIGKILL 和 SIGTERM 发送到 mysqld 进程的示例脚本是:

#! /usr/bin/env stap
#
# This systemtap script will monitor for SIGKILL and SIGTERM signals send to
# a process named "mysqld".
#
probe signal.send {
  if (
    (sig_name == "SIGKILL" || sig_name == "SIGTERM")
    && pid_name == "mysqld"
  ) {
    printf("%10d   %-34s   %-10s   %5d   %-7s   %s\n",
      gettimeofday_s(), tz_ctime(gettimeofday_s()),
      pid_name, sig_pid, sig_name, execname());
  }
}
probe begin {
  printf("systemtap script started at: %s\n\n", tz_ctime(gettimeofday_s()));
  printf("%50s%-18s\n",
    "",  "Signaled Process");
  printf("%-10s   %-34s   %-10s   %5s   %-7s   %s\n",
    "Epoch", "Time of Signal", "Name", "PID", "Signal", "Signaling Process Name");
  printf("---------------------------------------------------------------");
  printf("---------------------------------------------------------------");
  printf("\n");
}
probe end {
  printf("\n");
}

注意:以上脚本仅作为示例。
在生产中使用之前,请在测试系统上进行测试。

将脚本保存到文件中(以下假设文件名为 mysqld_kill_or_term.stp)。
用法是:

# stap mysqld_kill_or_term.stp
systemtap script started at: Fri Dec 18 13:35:44 2015 AEDT
                                                  Signaled Process
Epoch        Time of Signal                       Name           PID   Signal    Signaling Process Name
-----------------------------------------------------------------------------------------------------------------------------
1450406150   Fri Dec 18 13:35:50 2015 AEDT        mysqld       21578   SIGKILL   mykill
1450406161   Fri Dec 18 13:36:01 2015 AEDT        mysqld       21942   SIGKILL   mykill
1450406171   Fri Dec 18 13:36:11 2015 AEDT        mysqld       22045   SIGTERM   mykill
^C
在 Linux 上如何查找哪个进程使用 SIGKILL 或者 SIGTERM 在杀 mysqld

要确定哪个进程正在向 mysqld 发送信号,需要通过 Linux 内核跟踪信号。
执行此操作的两个选项是:

  • 审计日志(auditd)
  • systemtap
日期:2020-09-17 00:13:38 来源:oir作者:oir