Linux Magic System Request Key Hacks (翻译 by chatgpt)

发布时间 2023-12-01 21:26:11作者: 摩斯电码

原文:https://www.kernel.org/doc/html/latest/admin-guide/sysrq.html

What is the magic SysRq key?

什么是魔术SysRq键?

It is a 'magical' key combo you can hit which the kernel will respond to regardless of whatever else it is doing, unless it is completely locked up.
这是一个“神奇”的组合键,无论内核正在做什么,除非完全死机,否则内核都会对其做出响应。

How do I enable the magic SysRq key?

如何启用魔术SysRq键?

You need to say "yes" to 'Magic SysRq key (CONFIG_MAGIC_SYSRQ)' when configuring the kernel. When running a kernel with SysRq compiled in, /proc/sys/kernel/sysrq controls the functions allowed to be invoked via the SysRq key. The default value in this file is set by the CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE config symbol, which itself defaults to 1. Here is the list of possible values in /proc/sys/kernel/sysrq:
在配置内核时,需要对“Magic SysRq key (CONFIG_MAGIC_SYSRQ)”选择“是”。在运行已编译了SysRq的内核时,/proc/sys/kernel/sysrq控制可以通过SysRq键调用的功能。该文件中的默认值由CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE配置符号设置,默认为1。以下是/proc/sys/kernel/sysrq中可能的值列表:

  • 0 - disable sysrq completely
    0 - 完全禁用sysrq

  • 1 - enable all functions of sysrq
    1 - 启用sysrq的所有功能

  • >1 - bitmask of allowed sysrq functions (see below for detailed function description):
    >1 - 允许sysrq功能的位掩码(有关详细功能描述,请参见下文):

          2 =   0x2 - enable control of console logging level
                      启用控制台日志记录级别的控制
          4 =   0x4 - enable control of keyboard (SAK, unraw) 
                      启用键盘控制(SAK,取消原始模式)
          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)
                      启用进程信号(终止、杀死、oom-kill)
        128 =  0x80 - allow reboot/poweroff
                      允许重启/关机
        256 = 0x100 - allow nicing of all RT tasks
                      允许对所有RT任务进行优先级调整

You can set the value in the file by the following command:
您可以使用以下命令设置文件中的值:

echo "number" >/proc/sys/kernel/sysrq

The number may be written here either as decimal or as hexadecimal with the 0x prefix. CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE must always be written in hexadecimal.
该数字可以以十进制或带有0x前缀的十六进制形式写在此处。CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE必须始终以十六进制写入。

Note that the value of /proc/sys/kernel/sysrq influences only the invocation via a keyboard. Invocation of any operation via /proc/sysrq-trigger is always allowed (by a user with admin privileges).
请注意,/proc/sys/kernel/sysrq的值仅影响通过键盘的调用。始终允许使用/admin权限的用户通过/proc/sysrq-trigger调用任何操作。

How do I use the magic SysRq key?

如何使用魔术SysRq键?

On x86

You press the key combo ALT-SysRq-<command key>.
按下组合键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.
注意
有些键盘可能没有标有“SysRq”的键。'SysRq'键也被称为'Print Screen'键。此外,有些键盘无法同时处理这么多按键,因此您可能更容易成功按下Alt,按下SysRq,释放SysRq,按下,然后释放所有按键。

On SPARC
You press ALT-STOP-<command key>, I believe.

On the serial console (PC style standard serial ports only)
在串行控制台上(仅适用于PC样式的标准串行端口)

You send a BREAK, then within 5 seconds a command key. Sending BREAK twice is interpreted as a normal BREAK.
发送BREAK,然后在5秒内发送一个命令键。发送两次BREAK将被解释为正常的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 submit a patch to be included in this section.

On all
Write a character to /proc/sysrq-trigger. e.g.:
将一个字符写入/proc/sysrq-trigger。例如:

`echo t > /proc/sysrq-trigger`

The <command key> is case sensitive.
区分大小写。

What are the 'command' keys?

Command Function
b Will immediately reboot the system without syncing or unmounting your disks. 立即重新启动系统,而不进行同步或卸载磁盘。
c Will perform a system crash and a crashdump will be taken if configured. 执行系统崩溃,并在配置时进行崩溃转储。
d Shows all locks that are held. 显示所有已持有的锁。
e Send a SIGTERM to all processes, except for init. 向除init之外的所有进程发送SIGTERM信号。
f Will call the oom killer to kill a memory hog process, but do not panic if nothing can be killed. 调用oom killer来杀死一个占用内存的进程,但如果无法杀死任何进程,则不会发生恐慌。
g Used by kgdb (kernel debugger) 由kgdb(内核调试器)使用
h Will display help (actually any other key than those listed here will display help. but h is easy to remember ) 显示帮助(实际上除了这里列出的键之外的任何键都会显示帮助,但h易于记忆)
i Send a SIGKILL to all processes, except for init. 向除init之外的所有进程发送SIGKILL信号。
j Forcibly "Just thaw it" - filesystems frozen by the FIFREEZE ioctl. 强制“Just thaw it”-解冻通过FIFREEZE ioctl冻结的文件系统。
k Secure Access Key (SAK) Kills all programs on the current virtual console. NOTE: See important comments below in SAK section. 安全访问键(SAK)会杀死当前虚拟控制台上的所有程序。注意:请参阅SAK部分中的重要注释。
l Shows a stack backtrace for all active CPUs. 显示所有活动CPU的堆栈回溯。
m Will dump current memory info to your console. 将当前内存信息转储到控制台。
n Used to make RT tasks nice-able 用于使实时任务可优先级调整
o Will shut your system off (if configured and supported). 将关闭系统(如果已配置和支持)。
p Will dump the current registers and flags to your console. 将当前寄存器和标志转储到控制台。
q Will dump per CPU lists of all armed hrtimers (but NOT regular timer_list timers) and detailed information about all clockevent devices. 将转储所有已启用的hrtimers(但不是常规timer_list计时器)和有关所有clockevent设备的详细信息的每个CPU列表。
r Turns off keyboard raw mode and sets it to XLATE. 关闭键盘原始模式并将其设置为XLATE
s Will attempt to sync all mounted filesystems. 尝试同步所有已挂载的文件系统。
t Will dump a list of current tasks and their information to your console. 将当前任务及其信息转储到控制台。
u Will attempt to remount all mounted filesystems read-only. 尝试将所有已挂载的文件系统重新挂载为只读。
w Dumps tasks that are in uninterruptible (blocked) state. 转储处于不可中断(阻塞)状态的任务。
z Dump the ftrace buffer 转储ftrace缓冲区
0-9 Sets the console log level, controlling which kernel messages will be printed to your console. (0, for example would make it so that only emergency messages like PANICs or OOPSes would make it to your console.) 设置控制台日志级别,控制将打印到控制台的内核消息。(例如,0将使只有紧急消息(如PANIC或OOPS)才能打印到控制台。)

Okay, so what can I use them for?

好的,那么我可以用它们做什么?

Well, unraw(r) is very handy when your X server or a svgalib program crashes.
当您的X服务器或svgalib程序崩溃时,unraw(r)非常有用。

sak(k) (Secure Access Key) is useful when you want to be sure there is no trojan program running at console which could grab your password when you would try to login. It will kill all programs on given console, thus letting you make sure that the login prompt you see is actually the one from init, not some trojan program.
sak(k)(安全访问键)在您希望确保控制台上没有运行可能在您尝试登录时获取密码的特洛伊程序时非常有用。它将杀死给定控制台上的所有程序,从而确保您看到的登录提示实际上是来自init的提示,而不是来自某个特洛伊程序。

Important
In its true form it is not a true SAK like the one in a c2 compliant system, and it should not be mistaken as such.
重要提示
它的真实形式不是符合c2系统中的真正SAK,不应将其误认为是。

It seems others find it useful as (System Attention Key) which is useful when you want to exit a program that will not let you switch consoles. (For example, X or a svgalib program.)
其他人似乎将其用作(系统注意键),当您想要退出一个不允许您切换控制台的程序时非常有用。(例如,X或svgalib程序。)

reboot(b) is good when you're unable to shut down, it is an equivalent of pressing the "reset" button.
reboot(b)在无法关闭计算机时非常有用,它相当于按下“重置”按钮。

crash(c) can be used to manually trigger a crashdump when the system is hung. Note that this just triggers a crash if there is no dump mechanism available.
crash(c)可用于在系统挂起时手动触发崩溃转储。请注意,如果没有可用的转储机制,这只会触发崩溃。

sync(s) is handy before yanking removable medium or after using a rescue shell that provides no graceful shutdown -- it will ensure your data is safely written to the disk. Note that the sync hasn't taken place until you see the "OK" and "Done" appear on the screen.
sync(s)在拔出可移动介质之前或使用提供没有正常关机的救援shell之后非常有用-它将确保您的数据安全写入磁盘。请注意,直到屏幕上出现“OK”和“Done”字样,同步才完成。

umount(u) can be used to mark filesystems as properly unmounted. From the running system's point of view, they will be remounted read-only. The remount isn't complete until you see the "OK" and "Done" message appear on the screen.
umount(u)可用于将文件系统标记为已正确卸载。从运行中的系统的角度来看,它们将被重新挂载为只读。在屏幕上出现“OK”和“Done”消息之前,重新挂载尚未完成。

The loglevels 0-9 are useful when your console is being flooded with kernel messages you do not want to see. Selecting 0 will prevent all but the most urgent kernel messages from reaching your console. (They will still be logged if syslogd/klogd are alive, though.)
日志级别0-9在您的控制台被大量内核消息淹没时非常有用。选择0将阻止除最紧急的内核消息之外的所有消息进入控制台。(如果syslogd/klogd仍在运行,它们仍将被记录。)

term(e) and kill(i) are useful if you have some sort of runaway process you are unable to kill any other way, especially if it's spawning other processes.
term(e)和kill(i)在您无法以其他方式杀死某个失控进程时非常有用,特别是如果它正在生成其他进程。

"just thaw it(j)" is useful if your system becomes unresponsive due to a frozen (probably root) filesystem via the FIFREEZE ioctl.
“just thaw it(j)”在系统由于通过FIFREEZE ioctl冻结的(可能是根)文件系统而无响应时非常有用。

Sometimes SysRq seems to get 'stuck' after using it, what can I do?

有时候使用SysRq之后似乎会出现“卡住”的情况,我该怎么办?

When this happens, try tapping shift, alt and control on both sides of the keyboard, and hitting an invalid sysrq sequence again. (i.e., something like alt-sysrq-z).

Switching to another virtual console (ALT+Fn) and then back again should also help.

当出现这种情况时,尝试在键盘两侧同时按下shift、alt和control,并再次按下一个无效的sysrq序列(例如,类似alt-sysrq-z的组合键)。切换到另一个虚拟控制台(ALT+Fn),然后再切换回来也有助于解决问题。

I hit SysRq, but nothing seems to happen, what's wrong?

我按下了SysRq键,但似乎没有任何反应,出了什么问题?

There are some keyboards that produce a different keycode for SysRq than the pre-defined value of 99 (see KEY_SYSRQ in include/uapi/linux/input-event-codes.h), or which don't have a SysRq key at all. In these cases, run showkey -s to find an appropriate scancode sequence, and use setkeycodes <sequence> 99 to map this sequence to the usual SysRq code (e.g., setkeycodes e05b 99). It's probably best to put this command in a boot script. Oh, and by the way, you exit showkey by not typing anything for ten seconds.
有些键盘对于SysRq的键码与预定义值99(参见include/uapi/linux/input-event-codes.h中的KEY_SYSRQ)不同,或者根本没有SysRq键。在这些情况下,可以运行showkey -s来查找适当的扫描码序列,然后使用setkeycodes <sequence> 99将该序列映射到通常的SysRq代码(例如,setkeycodes e05b 99)。最好将这个命令放在引导脚本中。顺便提一下,退出showkey的方法是在十秒内不输入任何内容。

I want to add SysRQ key events to a module, how does it work?

我想要将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'.
要向表中注册基本函数,首先必须包含头文件include/linux/sysrq.h,这将定义你需要的一切。接下来,必须创建一个sysrq_key_op结构,并填充它的A)键处理函数,B)在SysRQ打印帮助时显示的help_msg字符串,C)在调用处理程序之前打印的action_msg字符串。你的处理程序必须符合'sysrq.h'中的原型。

After the sysrq_key_op is created, you can call the kernel function register_sysrq_key(int key, const 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, const 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.
创建sysrq_key_op之后,可以调用内核函数register_sysrq_key(int key, const struct sysrq_key_op *op_p); 这将在表键'key'处注册op_p指向的操作,如果该表中的槽为空。在模块卸载时,必须调用函数unregister_sysrq_key(int key, const struct sysrq_key_op *op_p),这将从键'key'中移除op_p指向的键操作,只有在该槽当前注册了它时才会执行。这是为了防止自注册以来该槽已被覆盖。

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:
Magic SysRQ系统通过在键操作查找表中注册键操作来实现,该表在'drivers/tty/sysrq.c'中定义。这个键表在编译时注册了许多操作,但是它是可变的,并且有两个导出函数用于接口:

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. ?
当然,绝对不能在表中留下无效的指针。也就是说,当调用register_sysrq_key()的模块退出时,必须调用unregister_sysrq_key()来清理它使用的sysrq键表条目。表中的空指针总是安全的。 ?

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.
如果出于某种原因你感觉有必要从handle_sysrq调用的函数中调用handle_sysrq函数,你必须意识到你处于一个锁定状态(你也处于中断处理程序中,这意味着不要睡觉!),所以你必须调用__handle_sysrq_nolock。

When I hit a SysRq key combination only the header appears on the console?

当我按下SysRq组合键时,只有标题出现在控制台上?

Sysrq output is subject to the same console loglevel control as all other console output. This means that if the kernel was booted 'quiet' as is common on distro kernels the output may not appear on the actual console, even though it will appear in the dmesg buffer, and be accessible via the dmesg command and to the consumers of /proc/kmsg. As a specific exception the header line from the sysrq command is passed to all console consumers as if the current loglevel was maximum. If only the header is emitted it is almost certain that the kernel loglevel is too low. Should you require the output on the console channel then you will need to temporarily up the console loglevel using alt-sysrq-8 or:
Sysrq输出受到与所有其他控制台输出相同的控制台日志级别控制。这意味着,如果内核以“quiet”模式启动(这在发行版内核上很常见),输出可能不会出现在实际控制台上,尽管它会出现在dmesg缓冲区中,并且可以通过dmesg命令和/proc/kmsg的消费者访问。作为一个特殊的例外,sysrq命令的标题行会被传递给所有控制台消费者,就好像当前的日志级别是最大的一样。如果只有标题被输出,几乎可以肯定内核日志级别太低了。如果你需要在控制台通道上输出,则需要临时提高控制台日志级别,使用alt-sysrq-8或:

echo 8 > /proc/sysrq-trigger

Remember to return the loglevel to normal after triggering the sysrq command you are interested in.
触发你感兴趣的sysrq命令后,记得将日志级别恢复到正常。

I have more questions, who can I ask?

Just ask them on the linux-kernel mailing list:
linux-kernel@vger.kernel.org