crash部分命令用法

来源:互联网 发布:淘宝the mountain 编辑:程序博客网 时间:2024/06/05 23:43

Set
set [pid | taskp | [-c cpu] | -p] | [crash_variable [setting]] | -v
1、设置要显示的内容,内容一般以进程为单位。
Set pid 设置当前的内容为pid所代表的进程
Set taskp 设置当前的内容为十六制表示的taskp任务的内容
Set –p 设置当前的内容为panic任务的内容
Set -v 显示crash当前的内部变量
Set 不带参数,表示显示当前任务的内容
2、同时set命令也可以设置当前crash的内部变量
Set scroll on表示开启滚动条。
具体的内部变量可以通过set –v命令获得,也可以通过help set来查看帮助。

Ascii
把一个十六进制表示的字符串转化成ascii表示的字符串
Ascii 不带参数则显示ascii码表
Ascii number number所代表的ascii字符串

Struct
struct struct_name[.member[,member]][-o][-l offset][-rfu] [address | symbol]
[count | -c count]
显示结构体的具体内容(下面只介绍常用的,具体的可通过命令help struct查询)
注:如果crash关键字与name所表示的结构体名称不冲突,可以省略struct关键字。
Struct name 显示name所表示的结构体的具体结构
Struct name.member 显示name所表示的结构体中的member成员
Struct name –o 显示name所表示的结构体的具体结构,同时也显示每个成员的偏移量
注:如果crash关键字与name所表示的结构体名称不冲突,可以省略struct关键字。

Union
union union_name[.member[,member]] [-o][-l offset][-rfu] [address | symbol]
[count | -c count]
显示联合体的具体内容,用法与struct一致。

*
它是一个快捷键,用来取代struct和union。
Struct page == *page
Struct page == *page

P
p [-x|-d][-u] expression
Print的缩写,打印表达式的值。表达式可以为变量,也可以为结构体。
通过命令alias可以查看命令缩写的列表。
Px expression == p –x expression 以十六进制显示expression的值
Pd expression == p –d expression 以十进制显示expression的值
不加参数的print,则根据set设置来显示打印信息。

Whatis
whatis [struct | union | typedef | symbol]
搜索数据或者类型的信息
参数可以是结构体的名称、联合体的名称、宏的名称或内核的符号。

Sym
sym [-l] | [-M] | [-m module] | [-p|-n] | [-q string] | [symbol | vaddr]
把一个标志符转换到它所对应的虚拟地址,或者把虚拟地址转换为它所对应的标志符。
Sym –l 列出所有的标志符及虚拟地址
Sym –M 列出模块标志符的集合
Sym –m module name 列表模块name的虚拟地址
Sym vaddr 显示虚拟地址addr所代表的标志
Sym symbol 显示symbol标志符所表示的虚拟地址
Sym –q string 搜索所有包含string的标志符及虚拟地址

Dis
dis [-r][-l][-u][-b [num]] [address | symbol | (expression)] [count]
disassemble的缩写。把一个命令或者函数分解成汇编代码。
Dis symbol
Dis –l symbol

Bt
bt [-a|-g|-r|-t|-T|-l|-e|-E|-f|-F|-o|-O] [-R ref] [-I ip] [-S sp] [pid | task]
跟踪堆栈的信息。
Bt 无参数则显示当前任务的堆栈信息
Bt –a 以任务为单位,显示每个任务的堆栈信息
Bt –t 显示当前任务的堆栈中所有的文本标识符
Bt –f 显示当前任务的所有堆栈数据,通过用来检查每个函数的参数传递

Dev
dev [-i | -p]
显示数据关联着的块设备分配,包括端口使用、内存使用及PCI设备数据
Dev –I 显示I/O端口使用情况
Dev –p 显示PCI设备数据

Files
files [-l | -d dentry] | [-R reference] [pid | taskp]
显示某任务的打开文件的信息
Files 显示当前任务下所有打开文件的信息
File –l 显示被服务器锁住的文件的信息

Irq
irq [[[index ...] | -u] | -d | -b]
显示中断编号的所有信息
Irq 不加参数,则显示所有的中断
Irq index 显示中断编号为index的所有信息
Irq –u 仅仅显示正在使用的中断

Foreach
foreach [[pid | taskp | name | [kernel | user]] ...] command [flag] [argument]
跟C#中的foreach类似,为多任务准备的。它根据参数指定的任务中去查找command相关的内容。任务可以用pid、taskp、name来指定。如果未指定,则搜索所有的任务。形如:
Foreach bash task 表示搜索任务bash中的task相关数据。

当command为{bt,vm,task,files,net,set,sig,vtop}时,显示的内容与命令中的命令类似,只是加了foreach则显示所有任务,而不是单条任务。形如:
Foreach files 显示所有任务打开的文件

Runq
无参数。显示每个CPU运行队列中的任务。

Alias
alias [alias] [command string]
创建给定的命令的别名,如果未指定参数,则显示创建好的别名列表。
Command string可以是带各种参数的命令。

Mount
mount [-f] [-i] [-n pid|task] [vfsmount|superblock|devname|dirname|inode]
显示挂载的相关信息
Mount 不加参数,则显示所有已挂载的文件系统
Mount –f 显示每个挂载文件系统中已经打开的文件
Mount –I 显示每个挂载文件系统中的dirty inodes

Search
search [-s start] [ -[kKV] | -u | -p ] [-e end | -l length] [-m mask] -[cwh] value ...
搜索在给定范围的用户、内核虚拟内存或者物理内存。如果不指定-l length或-e end,则搜索虚拟内存或者物理内存的结尾。内存地址以十六进制表示。
-u 如果未指定start,则从当前任务的用户内存搜索指定的value
-k 如果未指定start,则从当前任务的内核内存搜索指定的value
-p 如果未指定start,则从当前任务的物理内存搜索指定的value
-c 后面则指定要搜索的字符串,这个搜索中很有用。

Vm
vm [-p | -v | -m | [-R reference] | [-f vm_flags]] [pid | taskp] ...
显示任务的基本虚拟内存信息。
-p 显示虚拟内存及转换后的物理内存信息

Net
net [-a] [[-s | -S] [-R ref] [pid | taskp]] [-n addr]
显示各种网络相关的数据
-a 显示ARP cache
-s 显示指定任务的网络信息
-S 与-s相似,但是显示的信息更为详细
该命令与foreach配合使用,能加快定位的速度。

Vtop
vtop [-c [pid | taskp]] [-u|-k] address ...
显示用户或内核虚拟内存所对应的物理内存。其中-u和-k分别表示用户空间和内核空间。

Ptov
ptov address ...
该命令与vtop相反。把物理内存转换成虚拟内存。


Btop
btop address ...
把一个十六进制表示的地址转换成它的分页号。

Ptob
ptob page_number ...
该命令与btop相反,是把一个分页号转换成地址。


Sig
sig [[-l] | [-s sigset]] | [-g] [pid | taskp] ...
显示一个或者多个任务的signal-handling数据
-l 列出信息的编号及名字
-g 显示指定任务线程组中所有的signal-handling数据

Waitq
waitq [ symbol ] | [ struct.member struct_addr ] | [ address ]
列出在等待队列中的所有任务。参数可以指定队列的名称、内存地址等。

Pte
pte contents ...
把一个十六进制表示的页表项转换为物理页地址和页的位设置

Swap
无参数。显示已经配置好的交换设备的信息。

Wr
wr [-u|-k|-p] [-8|-16|-32|-64] [address|symbol] value
根据参数指定的写内存。在定位系统出错的地方时,一般不使用该命令。

Eval
eval [-b][-l] (expression) | value
计算表达式的值,及把计算结果或者值显示为16、10、8和2进制。表达式可以有运算符,包括加减乘除移位等。
-b 统计2进制位数为1的索引编号。

List
list [[-o] offset] [-e end] [-s struct[.member[,member]]] [-H] start
显示链表的内容

Mach
mach [-cm]
显示机器的一些信息,如CPU主频等。
-c 显示每个CPU的结构体信息
-m 显示物理内存每段的映射

Log
log [-m]
显示内核的日志,以时间的先后顺序排列
-m 在每个消息前添加该消息的日志等级

Sys
sys [-c [name|number]] config
显示特殊系统的数据。不指定参数,则显示crash启动时打印的系统数据。
-c [name|number] 如果不指定参数,则显示所有的系统调用。否则搜索指定的系统调用。
Config 显示内核的配置。不过必须把CONFIG_IKCONFIG编进内核

Rd
rd [-dDsSupxmf][-8|-16|-32|-64][-o offs][-e addr] [address|symbol] [count]
显示指定内存的内容。缺少的输出格式是十六进制输出
-d 以十进制方式输出
-D 以十进制无符号输出
-8 只输出最后8位
-16 只输出最后16位
-32 只输出最后32位
-64 只输出最后64位
-o offs 开始地址的偏移量
-e addr 显示内存,直到到过地址addr为止
Address 开始的内存地址,以十六进制表示
Symbol 开始地址的标识符
Count 按多少位显示内存地址。如addr=1234,count=8,则显示34 12

Task
task [-R member[,member]] [pid | taskp] ...
显示指定内容或者进程的task_struct的内容。不指定参数则显示当前内容的task_struct的内容。
Pid 进程的pid
Taskp 十六进制表示的task_struct指针。
-R member

Extend
extend [shared-object ...] | [-u [shared-object ...]]
动态装载或卸载crash额外的动态链接库。

Repeat
repeat [-seconds] command
每隔seconds重复一次命令command,无限期的执行下去。

Timer
无参数。按时间的先后顺序显示定时器队列的数据。

Gdb
gdb command ...
用GDB执行命令command。

 

转自:

http://yalung929.blog.163.com/blog/static/2038982252013216102949487/

学习 crash命令和其他命令的结合使用方法。

crash是和kdump工具配套使用,用于解析kdump生成的vmcore文件。vmcore是内核的映像(实际上是整个内存的映像,一般来说我们会开启过滤功能,只记录内核页)。内核全部的数据结构都在这个映像里面。crash解析vmcore可以让我们看到触发kdump时刻系统的各种状态和内容,信息非常丰富,是定位分析内核问题的利器。

启动crash
SUSE11:

linux11:/var/log/dump/2012-03-16-21:18# crash /usr/lrsp/kdump/vmlinux-2.6.32.45-0.3-default /boot/vmlinux-2.6.32.45-0.3-default.gz vmcore

/var/log/dump/2012-03-16-21:18 vmcore文件所在目录;2.6.32.45-0.3-default是所用内核的版本号,可以用`uname -r`实现应景替换。
SUSE10

linux10:/var/log/dump/2012-03-16-21:18# crash /usr/lrsp/kdump/vmlinux-2.6.16.46-0.12-smp vmcore


对于早期版本,如果/usr/lrsp/kdump/目录只有一个vmlinux文件,则直接运行

crash /usr/lrsp/kdump/vmlinux vmcore


以上是针对ATAE环境的。ATAE部署的系统已经预置了包含内核的调试信息的vmlinux。其他环境可以安装debuginfo包或者自己编译vmlinux

显示内核日志
内核把日志打印到内核态的日志缓冲区内,用户态klogd负责读取并转发给syslog记录到磁盘。在内核故障时,可能无法记录到磁盘,但内核日志缓冲区里面一般会有记录。既然vmcore是内存映像,那么日志缓冲区也就在里面了。内核最后打印的日志往往是我们分析内核问题的起点。

crash> log | tail -n 20
92789.909817] Kernel panic - not syncing: Watchdog fired!!!!!!!!!!!!!!!!!!!!!!!!!
92789.909821]
92790.014379] Pid:31675, comm: bonnie++ Tainted: G M W N 2.6.32.45-0.3.2.3813.0.PTF-default #1
92790.014382] Call Trace:
92790.014405][<ffffffff810061dc>] dump_trace+0x6c/0x2d0
92790.014412][<ffffffff81398886>] dump_stack+0x69/0x73
92790.014416][<ffffffff81398908>] panic+0x78/0x19b
92790.014437][<ffffffffa012d0bc>] watchdog_fire+0x4c/0x50[hherwatchdog]
92790.014456][<ffffffff810583e4>] run_timer_softirq+0x174/0x240
92790.014461][<ffffffff810534bf>] __do_softirq+0xbf/0x170
92790.014466][<ffffffff810040bc>] call_softirq+0x1c/0x30
92790.014470][<ffffffff81005cfd>] do_softirq+0x4d/0x80
92790.014474][<ffffffff81053345>] irq_exit+0x85/0x90
92790.014478][<ffffffff8100525e>] do_IRQ+0x6e/0xe0
92790.014484][<ffffffff81003913>] ret_from_intr+0x0/0xa
92790.014507][<0000000000403b5d>]0x403b5d


查看内核日志的crash命令是log
crash是一个交互环境:
你可以输入help显示所有支持的命令;
你可以输入help <命令名>显示这个命令的帮助。
crash命令可以和外部得命令结合使用,比如log | tail -n 20 ,很灵活很强大。


显示系统信息

crash> sys
KERNEL: /root/vmlinux-2.6.32.45-0.3.2.3813.0.PTF-default
DEBUGINFO: /root/vmlinux-2.6.32.45-0.3.2.3813.0.PTF-default
DUMPFILE: ./vmcore [PARTIAL DUMP]
CPUS: 2
DATE: Fri Jul 618:30:412012
UPTIME: 1 days, 01:45:49
LOAD AVERAGE: 4.99, 4.31, 2.88
TASKS: 225
NODENAME: linux1114
RELEASE: 2.6.32.45-0.3.2.3813.0.PTF-default
VERSION: #1 SMP2011-08-2210:12:58 +0200
MACHINE: x86_64 (2128 Mhz)
MEMORY: 4 GB
PANIC: "[92789.909817] Kernel panic - not syncing: Watchdog fired!!!!!!!!!!!!!!!!!!!!!!!!!"
crash>



显示执行KDUMP的堆栈

crash> bt
PID: 31675 TASK: ffff880118be6580 CPU:0 COMMAND: "bonnie++"
#0 [ffff88000da03cd8] machine_kexec at ffffffff81020902
#1 [ffff88000da03d28] crash_kexec at ffffffff810875b0
#2 [ffff88000da03df8] panic at ffffffff81398a26
#3 [ffff88000da03e68] watchdog_fire at ffffffffa012d0bc
#4 [ffff88000da03e78] run_timer_softirq at ffffffff810583e4
#5 [ffff88000da03ee8] __do_softirq at ffffffff810534bf
#6 [ffff88000da03f38] call_softirq at ffffffff810040bc
#7 [ffff88000da03f50] do_softirq at ffffffff81005cfd
#8 [ffff88000da03f70] irq_exit at ffffffff81053345
#9 [ffff88000da03f80] do_IRQ at ffffffff8100525e
--- <IRQ stack> ---


这个是触发kdump的上下文。通过这个我们跟踪内核崩溃的运行轨迹。比如上面的堆栈是在说:cpu 0发生了中断,中断退出时执行定时器软中断,有一个定时器超时了触发了它绑定的函数watchdog_fire,进而执行panic函数,最终触发了kdump。(machine_kexec停止当前内核并拉起预置的kdump内核,kdump内核启动完毕后,执行kdump用户态程序,保存原内核对应的内存映像,这就是kdump的基本原理)。


显示进程列表

crash> ps | more
PID PPID CPU TASK ST %MEM VSZ RSS COMM
0 00 ffffffff8180c020 RU 0.00 0[swapper]
0 01 ffff88011bdea1c0 RU 0.00 0[swapper]
1 01 ffff88011bdca040 IN 0.010380 644 init
2 01 ffff88011bdce080 IN 0.00 0[kthreadd]
3 20 ffff88011bdd40c0 IN 0.00 0[migration/0]
4 20 ffff88011bdd8100 IN 0.00 0[ksoftirqd/0]
……

crash> ps | grep UN #显示所有D状态(TASK_UNINTERRUPTIBLE)的进程
845 2 1 ffff8801194e6340 UN 0.00 0[kjournald]
2216 1 1 ffff88011fe8e200 UN 0.019804 1252 syslog-ng
crash> ps | grep RU #显示所有R状态(TASK_RUNNING)的进程
0 00 ffffffff8180c020 RU 0.00 0[swapper]
0 01 ffff88011bdea1c0 RU 0.00 0[swapper]
2298 2 1 ffff8801196fe340 RU 0.00 0[kipmi0]
> 193206470 1 ffff880037adc4c0 RU 0.0121056 1768 perl #前面的">"表示该进程正在CPU上执行。
> 3167531666 0 ffff880118be6580 RU 0.011760 1140 bonnie++
crash> ps | grep IN #显示所有S状态(TASK_INTERRUPTIBLE)的进程
1 01 ffff88011bdca040 IN 0.010380 644 init
2 01 ffff88011bdce080 IN 0.00 0[kthreadd]
3 20 ffff88011bdd40c0 IN 0.00 0[migration/0]
……



显示进程的内核栈

crash> bt 7355 #可以看到是一个缺页异常处理过程,访存->缺页异常->分配->回收->休眠
PID: 7355 TASK: ffff81065a5967a0 CPU:7 COMMAND: "sshd"
#0 [ffff81065eeb9858] schedule at ffffffff802e916a
#1 [ffff81065eeb9930] cond_resched at ffffffff802e92df
#2 [ffff81065eeb9940] shrink_zone at ffffffff80169bc6
#3 [ffff81065eeb9ae0] try_to_free_pages at ffffffff8016b88e
#4 [ffff81065eeb9b80] __alloc_pages at ffffffff801664cc
#5 [ffff81065eeb9be0] read_swap_cache_async at ffffffff8017715e
#6 [ffff81065eeb9c20] swapin_readahead at ffffffff8016ceb9
#7 [ffff81065eeb9c70] __handle_mm_fault at ffffffff8016f178
#8 [ffff81065eeb9d10] do_page_fault at ffffffff802ec74b
#9 [ffff81065eeb9e00] error_exit at ffffffff8010bd19
exception RIP: copy_user_generic+147]
RIP: ffffffff801f9e93 RSP: ffff81065eeb9eb8 RFLAGS: 00010202
RAX: 0000000000000000 RBX: 0000000000000008 RCX: 0000000000000001
RDX: 0000000000000008 RSI: ffff810667391558 RDI: 00005555556bb6e0
RBP: 0000000000000008 R8: 0000000000000008 R9: ffff8106682145c0
R10: ffff81066886dc34 R11: ffffffff802b3f3b R12: ffff810667391540
R13: 00005555556bb6e0 R14: 0000000000000000 R15: 0000000000000000
ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0000
#10 [ffff81065eeb9ec0] sys_select at ffffffff801987dc
#11 [ffff81065eeb9f80] system_call at ffffffff8010ae42


查看内存使用信息

crash> kmem -i
PAGES TOTAL PERCENTAGE
TOTAL MEM 6151777 23.5 GB ----
FREE 27816 108.7 MB0% of TOTAL MEM
USED 6123961 23.4 GB99% of TOTAL MEM
SHARED 1755 6.9 MB0% of TOTAL MEM
BUFFERS 58232 KB 0% of TOTAL MEM
CACHED 418493016 GB 68% of TOTAL MEM
SLAB 15548 60.7 MB0% of TOTAL MEM

TOTAL HIGH 00 0% of TOTAL MEM
FREE HIGH 00 0% of TOTAL HIGH
TOTAL LOW 6151777 23.5 GB100% of TOTAL MEM
FREE LOW 27816 108.7 MB0% of TOTAL LOW

TOTAL SWAP 419496316 GB ----
SWAP USED 419496316 GB 100% of TOTAL SWAP
SWAP FREE 00 0% of TOTAL SWAP
crash>



查看数据结构

crash> ps |grep UN
845 2 1 ffff8801194e6340 UN 0.00 0[kjournald]#ffff8801194e6340就是该进程的task_struct的地址。
2216 1 1 ffff88011fe8e200 UN 0.019804 1252 syslog-ng
crash> struct task_struct ffff88011fe8e200
struct task_struct {
state = 2,
stack = 0xffff88011b268000,
usage = {
counter = 2
……


有了task_struct就几乎有了关于这个进程的一切,你可以通过它顺藤摸瓜,找到你想要的信息。

crash> struct task_struct | more #不给地址时,显示数据结构的成员定义。
struct task_struct {
volatile long int state;
void *stack;
atomic_t usage;
……
crash>
crash> struct task_struct.pid #显示指定成员的定义,以及偏移,偏移很重要。
struct task_struct {
[1176] pid_t pid;
}
crash> struct task_struct.pid ffff88011fe8e200 #显示指定成员的值。
pid = 2216,
crash>



查看全局变量

crash> p sysctl_tcp_rmem #p实际上是gdb命令,crash内嵌了gdbgdb的很多命令都可以用,可通过help gdb了解。
sysctl_tcp_rmem = $3 =
{4096,87380, 4194304}


查看per_cpu变量

crash> p per_cpu__irq_stat #变量名称irq_stat 加上"per_cpu__" 前缀
PER-CPU DATA TYPE:
irq_cpustat_t per_cpu__irq_stat; #变量类型声明
PER-CPU ADDRESSES:
[0]: ffff88000da13480 # 0cpu对应的变量地址
[1]: ffff88000da53480 # 1cpu对应的变量地址
crash> struct irq_cpustat_t ffff88000da13480 #显示0cpu地址对应的内容
struct irq_cpustat_t {
__softirq_pending = 538,
__nmi_count = 23198362,
……
}


查看某个指令地址对应的代码行
发生了oops,通过log看到了oops的地址

Unable to handle kernel NULL pointer dereference at 0000000000000010 RIP:
<ffffffff80280fa7>{sockfd_lookup+53}


ffffffff80280fa7处访问了空指针,那么是哪一行代码?无需对着汇编反推源码位置,直接一个命令搞定

crash> l *0xffffffff80280fa7
0xffffffff80280fa7 is in sockfd_lookup(net/socket.c:448).
443 }
444
445 if (file->f_op == &socket_file_ops)
446 return file->private_data; /* set in sock_map_fd */
447
448 inode = file->f_dentry->d_inode; #这一行:)
449 if (!S_ISSOCK(inode->i_mode)){
450 *err = -ENOTSOCK;
451 fput(file);
452 return NULL;

还有很多,大家多多敲help ……


在线使用crash剖析运行中的内核
前面介绍了crash可以从VMCORE中解析出内核的数据结构,帮助我们分析内核问题。既然VMCORE是内存的映像,那么肯定也可以解析运行中的内核。这个会非常有用处,比如:
1. 某个进程D状态僵死了,系统还OK,这时候没必要对系统做KDUMP。而echo t >/proc/sysrq-trigger显示的信息又十分有限。而使用crash对运行内核做剖析,可以获取进程的方方面面,搞清楚问题所在。
2. 某些数据结构内核没有通过proc导出到外部,不能使用简单命令立即获取到,而这些数据结构对某些问题的分析又十分重要,使用crash对运行内核做剖析你可以获取到任何你想要的内容。比如一个tcp连接的全部状态信息,而不仅是/proc/net/tcp导出的那一点点。
3. Hack内核。你可以"偷窥"到内核的数据内容,比如页表。这对分析、学习内核源码会有很大的帮助。而且如果你比较"邪恶" :) 你可以修改它。进入crash输入help wr你就知道了。前不久suse11内核有一个计数溢出的BUG,需要400天才能重现,用wr命令修改了一个基础变量的值,立马就看到问题现象了,比重新编译内核快多了。

在线使用crash的方法很简单:
SUSE11:

# crash /boot/vmlinux-2.6.32.45-0.3.2.4445.1.PTF-default.gz /usr/lrsp/kdump/vmlinux-2.6.32.45-0.3.2.4445.1.PTF-default #实际上就是不指定vmcore文件路径。


SUSE10:

# crash -S /boot/System.map-2.6.16.60-0.21-smp /usr/lrsp/kdump/vmlinux-2.6.16.60-0.21-smp #不指定vmcore文件的路径,同时指定System.map


怎样查看变量的地址:

crash> sym boot_command_line
c05b114c (T) boot_command_line

 

 

 

0 0
原创粉丝点击