因为 syslogd 本身也被结束,所以 SysRq 也许不会被记录下来。但是查看 /var/log/messages 会看到类似下面的消息:
exiting on signal 15(SIGTERM) |
I - 向除 init 以外所有进程发送 SIGKILL 信号
SysRq: Kill All Tasks |
与 E 类似,因为 syslogd 本身也被结束,除非 netconsole 或串口记录已打开,否则连上面的信息都无法捕捉。同时,因为 SIGKILL 是不可捕获的信号,/var/log/messages 里面也不会留下任何线索。
S - 磁盘缓冲区同步
SysRq : Emergency Sync Emergency Sync complete |
该操作会把磁盘缓冲区的数据回写,以防止数据丢失,通常会有一定延时。在能看到输出的情况下,请等到 ” Emergency Sync complete ” 过后再继续后续操作。否则,等十秒钟左右,再进行后续 SysRq 操作。
U - 重新挂载为只读模式
SysRq : Emergency Remount R/O Emergency Remount complete |
该操作会把磁盘重挂载为只读模式,以防止数据的损坏。与 S 类似,该操作通常也有一定延时。请等到 ” Emergency Remount complete ” 出现过后再进行后续操作,或者等候十秒钟再进行后续 SysRq 操作。
B - 立即重启系统
SysRq: Resetting |
该操作会立即重启系统,比想象中要快。
恢复系统挂起
仅从系统挂起后安全重启来看,R-E-I-S-U-B 序列似乎已经令人满意了。但对于一些挂起,只是因为一部分进程消耗过多 CPU,内存等系统资源引起的。对于这样的情形,可以通过结束“凶手”进程来恢复已经挂起的系统。
笔者曾亲历 Acrobat Reader 在 Firefox 中内存泄露引起的系统挂起。每在 Firefox 中浏览完成一个 PDF 后,acroread 进程不会退出,相反其内存使用量逐步攀升,在一段时间内消耗完系统的内存和 swap,系统持续 swapping,使系统进入挂起状态,不响应桌面,鼠标,以及所有的应用程序。
笔者还经历一例屏保程序引起的系统挂起。锁定一段时间后,键盘鼠标停止响应,无法切换到本地控制台,远程登录正常,查看内存使用正常,CPU 被屏保程序吃尽。
SysRq 定义了一组与结束进程相关的序列:E-I-K-F,我们可以用它们来恢复系统挂起。
E 和 I 已经介绍过,他们都会结束除 init 以外的所有进程,理所当然都可以恢复类似的系统挂起。笔者在早期也是这样做的。但是这种方法似乎过于暴力,恢复过后的系统基本上除了 uptime 是连续的,数据未损坏以外,余下的状态并不比重启一次系统好。因为所有的服务都已中止,还需手工干预才能恢复正常。笔者的经验,经过 E-I 恢复的系统,如不是时间紧迫,即使系统已经恢复响应,最好继续完成 S-U-B 操作。因为对于一些复杂业务系统,难免因为人为因素造成某些服务忘记启动而埋下日后的定时炸弹。
K 和 F 正是它们的补充。它们仅结束符合特定条件的进程。 K 只结束与当前控制台相关的进程组。 K 代表 saK,saK 的全称为 Secure Access Key 。从字面意思看似乎有些深奥,它的本意是出于安全考虑,为了杀掉类似木马一类套取密码的伪登录程序,让 init 重新启动正在的 getty 登录界面。但在实际应用过程中,特别在 X 窗口下某些程序内存泄露或其它异常行为引起系统挂起时,就像上面两个例子,可以相当准确而快捷的使系统恢复正常。在理解 SysRq-K 之前,笔者曾一度使用 SysRq-E 来解决问题,但随之而来的系统服务恢复则成了一大难题。 F 则利用 OOM-Killer 选取一个进程然后结束之。这对于内存问题引起的挂起可以起到比 SysRq-K 更加准确的作用。但是有些时候 OOMKiller 也会误判而杀掉一些长时间运行的后台服务,引起一些不必要的麻烦。
下面列出各个序列的示例输出及简单说明:
E - 向所有进程发送 SIGTERM 信号
SysRq: Terminate All Tasks |
I - 向所有进程发送 SIGKILL 信号
SysRq: Kill All Tasks |
K - 结束与当前控制台相关的全部进程
SysRq : SAK SAK: killed process 7254 (top): p->signal->session==tty->session SAK: killed process 7223 (bash): p->signal->session==tty->session |
该操作结束了文本控制台下正在运行的 top 程序,以及登录的 shell 。
F - 人为触发 OOM Killer
SysRq : Manual OOM execution events/0 invoked oom-killer: gfp_mask=0xd0, order=0, oomkilladj=0 [<c04584e9>] out_of_memory+0x72/0x1a5 [<c053a2eb>] moom_callback+0x13/0x15 [<c04331de>] run_workqueue+0x78/0xb5 [<c053a2d8>] moom_callback+0x0/0x15 [<c0433a92>] worker_thread+0xd9/0x10b [<c042027b>] default_wake_function+0x0/0xc [<c04339b9>] worker_thread+0x0/0x10b [<c0435ea1>] kthread+0xc0/0xeb [<c0435de1>] kthread+0x0/0xeb [<c0405c3b>] kernel_thread_helper+0x7/0x10 ======================= Mem-info: …… (snip) …… Out of memory: Killed process 4860 (xfs). |
该操作人为触发 OOM Killer,OOM Killer 将根据各进程的内存处理情况选取最合适的“凶手”进程,并向其发送 SIGKILL 信号,中止其运行。 SysRq 输出包括运行栈,内存使用信息,和“凶手”进程的标识信息。在此例中 PID 为 4860 的 xfs 进程被中止。在实际情况中,除非可以确认是内存使用问题,尽量避免使用这个组合键。因为 OOM-Killer 自动挑选的进程不一定是真正的“凶手”。相比之下,SysRq-K 结束的进程更有针对性,特别是对 X 桌面下程序引起的系统挂起。由于桌面下启动的程序多数为非关键应用,结束并重启它们在大多数情况下并不会对系统造成太多影响。
考虑篇幅关系,省略了内存情况的输出,因为这部分与 SysRq-M 输出一致。
获取系统信息
SysRq 提供了 M-P-T-W 序列,在恢复系统挂起之前,这是一个推荐执行的序列。它会记录下当前系统的内存使用情况,当前 CPU 寄存器的状态,进程运行状态,以及所有 CPU 及寄存器的状态。通过这些信息,可以对挂起的原因做粗略的分析,然后结合之前介绍的 E-I-K-F 序列对症下药进行恢复性操作,或许还可以即时恢复一部分已经挂起的系统,而不是每遇到系统挂起就盲目的按电源,或机械地操作 R-E-I-S-U-B 序列。就算不能找到原因并成功恢复,也将会为以后的故障分析留下宝贵的证据。要知道,能通过 syslog 找出原因的系统挂起少之又少。
下面列出各个序列的示例输出及简单说明:
M - 打印内存使用信息
SysRq : Show Memory Mem-info: DMA per-cpu: cpu 0 hot: high 0, batch 1 used:0 cpu 0 cold: high 0, batch 1 used:0 DMA32 per-cpu: empty Normal per-cpu: cpu 0 hot: high 186, batch 31 used:12 cpu 0 cold: high 62, batch 15 used:13 HighMem per-cpu: empty Free pages: 94460kB (0kB HighMem) Active:34941 inactive:64962 dirty:1 writeback: 0 unstable:0 free:23615 slab:3755 mapped-file:2075 mapped-anon:7412 pagetables:3 26 DMA free:12016kB min:88kB low:108kB high:132kB active:16kB inactive:0kB present:16384kB pages_scanned:0 all_unreclaimable? no lowmem_reserve[]: 0 0 496 496 DMA32 free:0kB min:0kB low:0kB high:0kB active :0kB inactive:0kB present:0kB pages_scanned:0 all_unreclaimable? no lowmem_reserve[]: 0 0 496 496 Normal free:82444kB min:2804kB low:3504kB high :4204kB active:139748kB inactive:259848kB present:507904kB pages_scanned:0 all_u nreclaimable? no lowmem_reserve[]: 0 0 0 0 HighMem free:0kB min:128kB low:128kB high:128k B active:0kB inactive:0kB present:0kB pages_scanned:0 all_unreclaimable? no lowmem_reserve[]: 0 0 0 0 DMA: 38*4kB 37*8kB 33*16kB 29*32kB 24*64kB 17* 128kB 9*256kB 4*512kB 0*1024kB 1*2048kB 0*4096kB = 12016kB DMA32: empty Normal: 1*4kB 1*8kB 124*16kB 110*32kB 54*64kB 52*128kB 103*256kB 31*512kB 20*1024kB 2*2048kB 0*4096kB = 82444kB HighMem: empty 92491 pagecache pages Swap cache: add 0, delete 0, find 0/0, race 0+ 0 Free swap = 1048568kB Total swap = 1048568kB Free swap: 1048568kB 131072 pages of RAM 0 pages of HIGHMEM 2263 reserved pages 26019 pages shared 0 pages swap cached 1 pages dirty 0 pages writeback 2075 pages mapped 3755 pages slab 326 pages pagetables |