SysRq相关链接(写的很详细):
https://www.ibm.com/developerworks/cn/linux/l-cn-sysrq/
什么是SysRq?
你是否遇到服务器不能通过 SSH 登录,也不能通过本地终端(tty)登录的情况?
在这种情况下,你除了按下电源或复位键之外,还做过什么吗?
你是否想过这种情况是可能恢复的呢?
你是否想过收集更多的信息来定位这次系统挂起的原因呢?
--上述情况,可称之为“可中断的系统挂起”。
换句话来讲,系统因为某种原因已经停止对大部分正常服务的响应,但是系统仍然可以响应键盘的按键中断(实际应该是串口中断)请求。
Sysrq被称为”魔术组合键”, 是内建于Linux内核的调试工具,你可以按下它,内核会做出响应。
它被定义为一系列按键组合。之所以称它“magic”,是因为它在系统挂起,大多数服务已无法响应的情况下,还能通过按键组合来完成一系列预先定义的系统操作。
只要内核没有完全锁住,不管内核在做什么事情,使用这些组合键都可以搜集包括系统内存使用、CPU任务处理、进程运行状态等系统运行信息。
通过它,不但可以在保证磁盘数据安全的情况下重启一台挂起的服务器,避免数据丢失和重启后长时间的文件系统检查,
还可以收集包括系统内存使用,CPU 任务处理,进程运行状态等系统运行信息,甚至还可能在无需重启的情况下挽回一台已经停止响应的服务器。
如何启动SysRq?
需要在内核的“make menuconfig”中配置“CONFIG_MAGIC_SYSRQ”
当运行编译了SysRq的内核后,可以在“/proc/sys/kernel/sysrq”中控制允许通过哪些函数调用SysRq键。
下面是“/proc/sys/kernel/sysrq”可能的值列表(原文在Linux.x.x/Documentation/sysrq.txt):
Here is the list of possible values in /proc/sys/kernel/sysrq:
0 - disable sysrq completely
1 - enable all functions of sysrq
>1 - bitmask of allowed sysrq functions (see below for detailed function description):
2 = 0x2 - enable control of console logging level
4 = 0x4 - enable control of keyboard (SAK, unraw)
8 = 0x8 - enable debugging dumps of processes etc.
16 = 0x10 - enable sync command
32 = 0x20 - enable remount read-only
64 = 0x40 - enable signalling of processes (term, kill, oom-kill)
128 = 0x80 - allow reboot/poweroff
256 = 0x100 - allow nicing of all RT tasks
您可以通过以下命令设置SysRq文件中的值:
echo "number" >/proc/sys/kernel/sysrq
如果需要永久启用或者禁用SysRqs, 则可在/etc/sysctl.conf中设置:
kernel.sysrq = 1 (启用SsyRq)
kernel.sysrq = 0 (禁用SysRq)
kernel.sysrq 还可接受除 0 和 1 以外的启用参数,详情请参考sysrq内核文档。
如何使用SysRq?
这个在不同的平台上,使用SysRq的方法也不同,直接摘抄原文如下:
On x86 - You press the key combo 'ALT-SysRq-<command key>'. Note - Some
keyboards may not have a key labeled 'SysRq'. The 'SysRq' key is
also known as the 'Print Screen' key. Also some keyboards cannot
handle so many keys being pressed at the same time, so you might
have better luck with "press Alt", "press SysRq", "release SysRq",
"press <command key>", release everything.
On SPARC - You press 'ALT-STOP-<command key>', I believe.
On the serial console (PC style standard serial ports only) -
You send a BREAK, then within 5 seconds a command key. Sending
BREAK twice is interpreted as a normal BREAK.
On PowerPC - Press 'ALT - Print Screen (or F13) - <command key>,
Print Screen (or F13) - <command key> may suffice.
On other - If you know of the key combos for other architectures, please
let me know so I can add them to this section.
On all - write a character to /proc/sysrq-trigger. e.g.:
echo t > /proc/sysrq-trigger
sysrq-trigger节点调试
内核配置选项中使能CONFIG_MAGIC_SYSRQ选项,这样系统启动之后,会生成/proc/sysrq-trigger节点用于调试。
注意,设置“/proc/sys/kernel/sysrq”的值只影响通过键盘的调用。
而“/proc/sysrq-trigger”节点能调用任何操作(具有管理特权的用户)
部分功能:
echo m > /proc/sysrq-trigger 导出内存分配信息
echo t > /proc/sysrq-trigger 导出当前任务状态信息
echo p > /proc/sysrq-trigger 导出当前CPU寄存器和标志位信息
echo c > /proc/sysrq-trigger 产生空指针panic事件,人为导致系统崩溃
echo s > /proc/sysrq-trigger 即时同步所有挂载的文件系统
echo u > /proc/sysrq-trigger 即时重新挂载所有的文件系统为只读
echo w > /proc/sysrq-trigger 转储处于uninterruptable阻塞状态的任务
魔术键有哪些“命令”?
魔术键使用帮助:
0-9 设定终端输出的内核 log 优先级
b 立即重启系统
c 内核live reboot,并输出错误信息
d 显示所有排它锁(显示所有被持有的锁)
e 向除 init 外进程发送 SIGTERM 信号,让其自行结束
f 人为触发 OOM Killer (out of memory)
g 当进入内核模式时,以 framebuttter 代替输出(kgdb(内核调试器)使用)
h 输出帮助
i 向除 init 以外所有进程发送 SIGKILL 信号,强制结束进程
k 安全访问密钥(SAK)杀死当前虚拟控制台上的所有程序
l 显示所有活动cpu的堆栈回溯。
m 内存使用信息(将当前内存信息转储到您的控制台。)
n 重置所有进程的 nice(优先级)
o 关机
p 输出cpu 寄存器信息
q Display all active high-resolution timers and clock sources.
r 把键盘设置为 ASCII 模式,使按键可以穿透 x server 捕捉传递给内核
s 同步缓冲区数据到硬盘
t 输出进程列表(将当前任务及其信息的列表转储到您的控制台。)
u 重新挂载所有文件系统为只读模式
v 输出 Voyager SMP 处理信息
w 输出 block(d状态)进程列表
我们能用SysRq做什么?
1.“k” - (安全访问密钥)是非常有用的,当你想要确保没有木马程序运行在控制台,伺机抓取你的密码
在您尝试登录时。它会杀死给定控制台的所有程序,
因此,您可以确保您看到的登录提示符实际上是来自init的,不是木马程序。
2.“b” - 当系统无法关闭时重启(b)是很好的。但是您还应该首先同步(s)和umount(u)。
3.“s” - 同步(s)是伟大的,当您的系统被锁定,它允许您同步您的磁盘,当然会减少数据丢失和fscking的机会。
请注意,在屏幕上出现“OK”和“Done”之前,不会进行同步。(如果内核真的处于冲突中,您可能永远得不到OK或Done消息……)
4.“u” - 解除挂载(u)基本上与sync(s)一样有用。我通常同步(s), 解除挂载(u),然后重启(b)当我的系统锁定。
它帮我省了很多操作。同样,在您看到屏幕上出现“OK”和“Done”消息之前,解除挂载(remount只读)还没有发生。
5.“0-9” - 当控制台被不想看到的内核消息淹没时,日志级别“0”-“9”非常有用。
选择“0”将阻止除最紧急的内核消息之外的所有消息到达您的控制台。
(不过,如果syslod /klogd是活动的,它们仍然会被记录下来。)
6.“e”,"i" - term(e)和kill(i)是有用的,如果你有某种失控的进程,
你不能用任何其他方法来杀死它,特别是当它生成其他进程时。
7."m" - 内存信息(m)是非常有用的,当系统处于卡死的状态,而你又想要查看当前系统的内存使用情况时。
8.“t” - 进程列表(t)可以打印当前所有的任务及其信息。用于查找一些异常的进程。
9.“p” - CPU寄存器(p)也是非常有用的,在系统卡住的时候,可以通过查看寄存器,找到当前的系统指针在哪个位置。
10.“R-E-I-S-U-B” - 安全重启系统。R-E-I-S-U-B 这个序列的推荐使用方式是:
R – 1 秒 – E – 30 秒 – I – 10 秒 – S – 5 秒 – U – 5 秒 – B,而不是一气呵成地按下这六个键,
试想一次正常的 reboot 命令也不是在一瞬间完成的吧。
R - 把键盘设置为 ASCII 模式
E - 向除 init 以外所有进程发送 SIGTERM 信号
I - 向除 init 以外所有进程发送 SIGKILL 信号
S - 磁盘缓冲区同步
U - 重新挂载为只读模式
B - 立即重启系统
点击了SysRq,但是什么也没有发生,为什么?
有些键盘为SysRq生成的键码与预定义的值99不同(请参阅include/linux/input.h中的KEY_SYSRQ),或者根本没有SysRq键。
我想添加一个事件到SysRq模块,应该怎么做?
我也不知道怎么做,因为我也没做过...
查阅资料,原文如下:
In order to register a basic function with the table, you must first include
the header 'include/linux/sysrq.h', this will define everything else you need.
Next, you must create a sysrq_key_op struct, and populate it with A) the key
handler function you will use, B) a help_msg string, that will print when SysRQ
prints help, and C) an action_msg string, that will print right before your
handler is called. Your handler must conform to the prototype in 'sysrq.h'.
After the sysrq_key_op is created, you can call the kernel function
register_sysrq_key(int key, struct sysrq_key_op *op_p); this will
register the operation pointed to by 'op_p' at table key 'key',
if that slot in the table is blank. At module unload time, you must call
the function unregister_sysrq_key(int key, struct sysrq_key_op *op_p), which
will remove the key op pointed to by 'op_p' from the key 'key', if and only if
it is currently registered in that slot. This is in case the slot has been
overwritten since you registered it.
The Magic SysRQ system works by registering key operations against a key op
lookup table, which is defined in 'drivers/tty/sysrq.c'. This key table has
a number of operations registered into it at compile time, but is mutable,
and 2 functions are exported for interface to it:
register_sysrq_key and unregister_sysrq_key.
Of course, never ever leave an invalid pointer in the table. I.e., when
your module that called register_sysrq_key() exits, it must call
unregister_sysrq_key() to clean up the sysrq key table entry that it used.
Null pointers in the table are always safe. :)
If for some reason you feel the need to call the handle_sysrq function from
within a function called by handle_sysrq, you must be aware that you are in
a lock (you are also in an interrupt handler, which means don't sleep!), so
you must call __handle_sysrq_nolock instead.
当我点击一个SysRq键组合,只有头出现在控制台?
Sysrq输出与所有其他控制台输出受相同的控制台日志级别控制。
这意味着,如果内核像发行版内核上常见的那样引导为“安静”,
那么输出可能不会出现在实际的控制台上,即使它会出现在dmesg缓冲区中,
并且可以通过dmesg命令和/proc/kmsg.的消费者访问作为一个特定的异常,
sysrq命令的头行被传递给所有控制台消费者,就好像当前日志级别是最大的一样。
如果只发出报头,几乎可以肯定内核日志级别太低。
如果您需要控制台通道上的输出,则需要使用alt-sysrq-8或:
echo 8 > /proc/sysrq-trigger
记住,在触发您感兴趣的sysrq命令后,将日志级别恢复到正常。
我还有更多的问题,我能问谁?
别问我,问他们!
只要在linux内核邮件列表中询问他们:
linux-kernel@vger.kernel.org
(ps:“h” - 查看魔术键的使用帮助)
sysrq: SysRq : HELP : loglevel(0-9) reboot(b) crash(c) terminate-all-tasks(e)
memory-full-oom-kill(f) kill-all-tasks(i) thaw-filesystems(j) sak(k)
show-backtrace-all-active-cpus(l) show-memory-usage(m) nice-all-RT-tasks(n)
poweroff(o) show-registers(p) show-all-timers(q) unraw(r) sync(s)
show-task-states(t) unmount(u) show-blocked-tasks(w)
(ps:“m” - 查看当前的内存使用情况)
sysrq: SysRq : Show Memory
Mem-Info:
active_anon:34588 inactive_anon:1508 isolated_anon:0
active_file:0 inactive_file:0 isolated_file:0
unevictable:0 dirty:0 writeback:0 unstable:0
slab_reclaimable:774 slab_unreclaimable:10682
mapped:2297 shmem:33632 pagetables:218 bounce:0
free:42392 free_pcp:88 free_cma:3934
Node 0 active_anon:138352kB inactive_anon:6032kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB mapped:9188kB dirty:0kB writeback:0kB shmem:134528kB writeback_tmp:0kB unstable:0kB pages_scanned:0 all_unreclaimable? yes
Normal free:169568kB min:8192kB low:10240kB high:12288kB active_anon:138352kB inactive_anon:6032kB active_file:0kB inactive_file:0kB unevictable:0kB writepending:0kB present:393216kB managed:380740kB mlocked:0kB slab_reclaimable:3096kB slab_unreclaimable:42728kB kernel_stack:968kB pagetables:872kB bounce:0kB free_pcp:352kB local_pcp:128kB free_cma:15736kB
lowmem_reserve[]: 0 0 0
Normal: 4*4kB (MEC) 2*8kB (ME) 2*16kB (EC) 3*32kB (MEC) 1*64kB (C) 1*128kB (E) 3*256kB (MEC) 3*512kB (UME) 1*1024kB (C) 3*2048kB (UMC) 39*4096kB (MC) = 169568kB
33632 total pagecache pages
98304 pages RAM
0 pages HighMem/MovableOnly
3119 pages reserved
4096 pages cma reserved
(ps:"l" - 查看当前的活动cpu的堆栈回溯)
sysrq: SysRq : Show backtrace of all active CPUs
NMI backtrace for cpu 1
CPU: 1 PID: 0 Comm: swapper/1 Tainted: P O 4.9.37 #396
Hardware name: Generic DT based system
[<c010f8b8>] (unwind_backtrace) from [<c010b4e0>] (show_stack+0x10/0x14)
[<c010b4e0>] (show_stack) from [<c03807bc>] (dump_stack+0x84/0x98)
[<c03807bc>] (dump_stack) from [<c0383f54>] (nmi_cpu_backtrace+0xc0/0xc4)
[<c0383f54>] (nmi_cpu_backtrace) from [<c038403c>] (nmi_trigger_cpumask_backtrace+0xe4/0x12c)
[<c038403c>] (nmi_trigger_cpumask_backtrace) from [<c03fca14>] (__handle_sysrq+0x120/0x174)
[<c03fca14>] (__handle_sysrq) from [<c040fd60>] (pl011_fifo_to_tty+0x19c/0x1f4)
[<c040fd60>] (pl011_fifo_to_tty) from [<c04106e4>] (pl011_int+0x254/0x44c)
[<c04106e4>] (pl011_int) from [<c015f7fc>] (__handle_irq_event_percpu+0x9c/0x124)
[<c015f7fc>] (__handle_irq_event_percpu) from [<c015f8a0>] (handle_irq_event_percpu+0x1c/0x58)
[<c015f8a0>] (handle_irq_event_percpu) from [<c015f920>] (handle_irq_event+0x44/0x68)
[<c015f920>] (handle_irq_event) from [<c0162d6c>] (handle_fasteoi_irq+0xb4/0x194)
[<c0162d6c>] (handle_fasteoi_irq) from [<c015eb28>] (generic_handle_irq+0x24/0x34)
[<c015eb28>] (generic_handle_irq) from [<c015f04c>] (__handle_domain_irq+0x5c/0xb4)
[<c015f04c>] (__handle_domain_irq) from [<c0101438>] (gic_handle_irq+0x48/0x8c)
[<c0101438>] (gic_handle_irq) from [<c010bfcc>] (__irq_svc+0x6c/0x90)
Exception stack(0xd6877f98 to 0xd6877fe0)
7f80: 00000000 023343d6
7fa0: d6cd62e8 c0115200 d6876000 c0a02fe4 00000002 c0a0304c c0a0d44a 410fd034
7fc0: 00000000 00000000 00000000 d6877fe8 c0108680 c0108684 60000013 ffffffff
[<c010bfcc>] (__irq_svc) from [<c0108684>] (arch_cpu_idle+0x38/0x3c)
[<c0108684>] (arch_cpu_idle) from [<c01528dc>] (cpu_startup_entry+0xc8/0x13c)
[<c01528dc>] (cpu_startup_entry) from [<22101528>] (0x22101528)
Sending NMI from CPU 1 to CPUs 0:
(ps:“p” - 打印输出CPU寄存器信息)
sysrq: SysRq : Show Regs
CPU: 1 PID: 0 Comm: swapper/1 Tainted: P O 4.9.37 #396
Hardware name: Generic DT based system
task: d6853440 task.stack: d6876000
PC is at arch_cpu_idle+0x38/0x3c
LR is at arch_cpu_idle+0x34/0x3c
pc : [<c0108684>] lr : [<c0108680>] psr: 60000013
sp : d6877fe8 ip : 00000000 fp : 00000000
r10: 00000000 r9 : 410fd034 r8 : c0a0d44a
r7 : c0a0304c r6 : 00000002 r5 : c0a02fe4 r4 : d6876000
r3 : c0115200 r2 : d6cd62e8 r1 : 023348a2 r0 : 00000000
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none
Control: 10c5383d Table: 230fc06a DAC: 00000051
CPU: 1 PID: 0 Comm: swapper/1 Tainted: P O 4.9.37 #396
Hardware name: Generic DT based system
[<c010f8b8>] (unwind_backtrace) from [<c010b4e0>] (show_stack+0x10/0x14)
[<c010b4e0>] (show_stack) from [<c03807bc>] (dump_stack+0x84/0x98)
[<c03807bc>] (dump_stack) from [<c03fca14>] (__handle_sysrq+0x120/0x174)
[<c03fca14>] (__handle_sysrq) from [<c040fd60>] (pl011_fifo_to_tty+0x19c/0x1f4)
[<c040fd60>] (pl011_fifo_to_tty) from [<c04106e4>] (pl011_int+0x254/0x44c)
[<c04106e4>] (pl011_int) from [<c015f7fc>] (__handle_irq_event_percpu+0x9c/0x124)
[<c015f7fc>] (__handle_irq_event_percpu) from [<c015f8a0>] (handle_irq_event_percpu+0x1c/0x58)
[<c015f8a0>] (handle_irq_event_percpu) from [<c015f920>] (handle_irq_event+0x44/0x68)
[<c015f920>] (handle_irq_event) from [<c0162d6c>] (handle_fasteoi_irq+0xb4/0x194)
[<c0162d6c>] (handle_fasteoi_irq) from [<c015eb28>] (generic_handle_irq+0x24/0x34)
[<c015eb28>] (generic_handle_irq) from [<c015f04c>] (__handle_domain_irq+0x5c/0xb4)
[<c015f04c>] (__handle_domain_irq) from [<c0101438>] (gic_handle_irq+0x48/0x8c)
[<c0101438>] (gic_handle_irq) from [<c010bfcc>] (__irq_svc+0x6c/0x90)
Exception stack(0xd6877f98 to 0xd6877fe0)
7f80: 00000000 023348a2
7fa0: d6cd62e8 c0115200 d6876000 c0a02fe4 00000002 c0a0304c c0a0d44a 410fd034
7fc0: 00000000 00000000 00000000 d6877fe8 c0108680 c0108684 60000013 ffffffff
[<c010bfcc>] (__irq_svc) from [<c0108684>] (arch_cpu_idle+0x38/0x3c)
[<c0108684>] (arch_cpu_idle) from [<c01528dc>] (cpu_startup_entry+0xc8/0x13c)
[<c01528dc>] (cpu_startup_entry) from [<22101528>] (0x22101528)