Linux "魔力" 系统请求组合键 SysRq

所谓 "魔力" 系统请求组合键 是指不论内核在做什么,都会响应这个组合键 magical key combo (除非内核完全锁死)。我们通常会使用 magic SysRq key 来实现内核级的调试信息输出。

如何激活magic SysRq key

首先在内核配置上,需要配置 CONFIG_MAGIC_SYSRQ=Y ,这样编译出来的支持SysRq的内核,启动后会提供一个 /proc/sys/kernel/sysrq 控制功能,允许使用SysRq键。

其次,在内核 CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 配置符号,默认设置是 1

激活SysRq功能: 内核配置 CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 或者 echo <SysRq配置值> > /proc/sys/kernel/sysrq

SysRq配置值

16进制

说明

0

0x0

关闭所有sysrq功能

1

0x1

激活所有sysrq功能

2

0x2

激活控制台日志级别控制

4

0x4

激活键盘控制(SAK,unraw)

8

0x8

激活进程的debug

16

0x10

激活sync命令

32

0x20

激活remount

64

0x40

激活进程信号(term,kill,oom-kill)

128

0x80

允许重启/关机

256

0x100

允许所有实时任务配置nice

  • 执行启用sysrq所有功能:

    echo 1 > /proc/sys/kernel/sysrq
    
  • 在完成sysrq的指令之后(见下文),可能需要关闭sysrq功能,则可以输入0:

    echo 0 > /proc/sys/kernel/sysrq
    

备注

这里的发送给 /proc/sys/kernel/sysrq 数字可以写成十进制或者带 0x 的十六进制,但是在内核配置 CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE 必须始终以十六进制编写。

/proc/sys/kernel/sysrq 的值仅影响通过键盘的调用,而在 /proc/sysrq-trigger 入口调用是始终允许的(需要系统管理员权限)

使用SysRq

在不同的硬件平台有着不同的组合键出发 SysRq :

备注

一些键盘没有标记为 SysRq 的按键,而 SysRq 键也称为 Print Screen 键。此外,一些键盘可能无法同时按下 SysRq 组合键,可以尝试按住 Alt 键不放,然后顺序按下 SysRq ,释放 SysRq 键,再按下 <命令键> ,然后释放所有键来完成触发。

SysRq组合键

不同平台

SysRq组合键

x86

ALT-SysRq-<命令键>

SPARC

ALT-STOP-<命令键>

PC主机串口

发送 BREAK (我记得是 ctrl+b ),并且在5秒内按下 <命令键> ,再按2次 BREAK 表示常规BREAK结束

PowerPC

ALT-Print Screen (or F13) - <command key>

所有平台

命令行发送字符给 /proc/sysrq-trigger

SysRq <命令键>

SysRq命令键

命令

功能

b

不sync系统或卸载磁盘挂载立即(强制)重启系统

c

触发一次系统crash,如果配置了kdump则触发Kernel dump

d

显示持有的所有锁

e

向除init进程外的所有进程发送 SIGTERM

f

调用 oom killer 来杀死内存占用进程,不过如果无法杀死也不要惊慌

g

kgdb 使用 (kernel debugger)

h

显示帮助

i

向除init进程外的所有进程发送 SIGKILL

j

强行"解冻它" - 通过 FIFREEZE ioctl 冻结的文件系统

k

安全访问密钥(Secure Access Key, SAK)杀死当前虚拟控制台上所有进程,注意参考下文SAK部分的重要注释

l

显示所有活动CPU的堆栈回溯(stack backtrace)

m

将当前内存信息转储(dump)到控制台

n

用于使RT任务更友好(nice-able)

o

关闭系统(如果已经配置和支持)

p

将当前寄存器和标志(registers and flags)转储到控制台

q

转储所有armed hrtimers(但 不是 常规 timeer_list 计时器)的每个CPU列表以及所有时钟事件(cloudevent)设备的详细信息

r

关闭键盘原始模式并将其设置为 XLATE

s

尝试同步所有已经挂载的文件系统

t

转储(dump)当前任务列表以及任务信息到控制台

u

尝试以只读方式重新挂载所有已经挂载的文件系统

v

强制恢复帧缓冲区控制台(framebuffer console)

v

触发ETM缓冲区转储(仅限ARM平台)

w

将处于不可中断(uninterruptable, blocked)状态的任务转储

x

由 ppc/powerpc 平台上的 xmon 接口使用, 在 sparc64 上显示全局 PMU 寄存器, 在 MIPS 上转储所有 TLB 条目

y

显示全局CPU寄存器(仅限SPARC-64平台)

z

转储ftrace缓存

0-9

设置控制台日志级别,控制哪些内核消息打印到控制台(例如,设置为0则表示只有像 PANICOOPS 紧急消息才会输出控制台

使用 SysRq t 排查 debug占用很高system的进程 是一个很好的方法( "Bad RIP value"含义 ),能够快速找出导致系统死锁的进程(在系统日志中会看到大量的 Call Trace ),通过 Call Trace 可以定位到大量系统调用以及锁信息。例如,我在排查 Kubernetes Atlas 管控服务器的 sys 高(CPU的 us 极低)就采用这个方法,定位到 prog-extension 进程出现 futex_wait (用户空间锁等待):

使用 echo t > /proc/sysrq-trigger 找出系统死锁进程
[Tue Feb 28 16:06:33 2023] prog-extensio S    0 51268  49038 0x00000000
[Tue Feb 28 16:06:33 2023]  ffff88355a77c200 0000000000000000 ffff8830ddaa4ec0 ffff883f7ed19f40
[Tue Feb 28 16:06:33 2023]  ffff883f64d50000 ffffc90031857c70 ffffffff8173ca3b ffff88355a77c200
[Tue Feb 28 16:06:33 2023]  0000000000000021 ffff883f7ed19f40 ffffc90019b94b88 ffff8830ddaa4ec0
[Tue Feb 28 16:06:33 2023] Call Trace:
[Tue Feb 28 16:06:33 2023]  [<ffffffff8173ca3b>] ? __schedule+0x23b/0x780
[Tue Feb 28 16:06:33 2023]  [<ffffffff8173cfb6>] schedule+0x36/0x80
[Tue Feb 28 16:06:33 2023]  [<ffffffff811194d4>] futex_wait_queue_me+0xc4/0x120
[Tue Feb 28 16:06:33 2023]  [<ffffffff8111a066>] futex_wait+0x116/0x270
[Tue Feb 28 16:06:33 2023]  [<ffffffff81119a70>] ? futex_wake+0x90/0x170
[Tue Feb 28 16:06:33 2023]  [<ffffffff8111c4e5>] do_futex+0x205/0x520
[Tue Feb 28 16:06:33 2023]  [<ffffffff810bf3c9>] ? sched_clock_cpu+0x99/0xb0
[Tue Feb 28 16:06:33 2023]  [<ffffffff8111c885>] SyS_futex+0x85/0x170
[Tue Feb 28 16:06:33 2023]  [<ffffffff81003c04>] do_syscall_64+0x74/0x180
[Tue Feb 28 16:06:33 2023]  [<ffffffff81741c8e>] entry_SYSCALL_64_after_swapgs+0x58/0xc6

警告

SysRq t 会触发控制台大量输出,大量控制台输出会导致服务器hang,需要注意

参考