- 1 crashコマンドとは?
- 2 検証環境
- 3 インストール方法
- 4 crashコマンド起動方法
- 5 コマンド一覧、ヘルプを表示する方法(help)
- 6 logコマンドの使い方
- 7 setコマンドの使い方
- 8 rdコマンドの使い方
- 9 modコマンドの使い方
- 10 netコマンドの使い方
- 11 disコマンドの使い方
- 12 taskコマンドの使い方
- 13 filesコマンドの使い方
- 14 fuserコマンドの使い方
- 15 symコマンドの使い方
- 16 listコマンドの使い方
- 17 treeコマンドの使い方
- 18 swapコマンドの使い方
- 19 repeatコマンドの使い方
- Z 参考情報
1 crashコマンドとは?
crashコマンドは、カーネルのデバッグ時に使用するコマンドです。カーネルに何らかの不具合が発生してクラッシュすると、vmcore(ダンプファイル)が生成されます。生成されたvmcoreをcrashコマンドで解析することで、カーネルクラッシュの原因を特定することができます。
2 検証環境
AlmaLinux版数は以下のとおりです。
[root@server ~]# cat /etc/redhat-release AlmaLinux release 8.6 (Sky Tiger)
カーネル版数は以下のとおりです。
[root@server ~]# uname -r 4.18.0-372.9.1.el8.x86_64
3 インストール方法
crashパッケージをインストールします。
[root@server ~]# dnf -y install crash
crashコマンドの版数は以下のとおりです。
[root@server ~]# crash --version crash 7.3.2-2.el8.alma -help-
kernel-debuginfoパッケージをインストールするため、リポジトリを追加します。
[root@server ~]# dnf config-manager --add-repo=https://repo.almalinux.org/vault/8.6/BaseOS/debug/x86_64/
kernel-debuginfoパッケージをインストールします。
[root@server ~]# dnf install kernel-debuginfo-4.18.0-372.9.1.el8
SysRq(echo c > /proc/sysrq_trigger)によりカーネルをクラッシュさせます。再起動後、/var/crash/配下に採取されたvmcoreを確認します。
[root@server ~]# ls -l /var/crash/127.0.0.1-2023-02-09-06\:08\:11/ 合計 65552 -rw-------. 1 root root 57723 2月 9 20:08 kexec-dmesg.log -rw-------. 1 root root 67007812 2月 9 20:08 vmcore -rw-------. 1 root root 49196 2月 9 20:08 vmcore-dmesg.txt
crashコマンドの引数に指定するカーネルを確認します。
[root@server ~]# ls -l /usr/lib/debug/lib/modules/4.18.0-372.9.1.el8.x86_64/vmlinux -rwxr-xr-x. 1 root root 925778760 5月 10 2022 /usr/lib/debug/lib/modules/4.18.0-372.9.1.el8.x86_64/vmlinux
4 crashコマンド起動方法
vmcoreとカーネルイメージを引数にしてcrashコマンドを実行します。
[root@server ~]# crash /var/crash/127.0.0.1-2023-02-09-06\:08\:11/vmcore /usr/lib/debug/lib/modules/4.18.0-372.9.1.el8.x86_64/vmlinux -snip- WARNING: kernel relocated [180MB]: patching 105260 gdb minimal_symbol values KERNEL: /usr/lib/debug/lib/modules/4.18.0-372.9.1.el8.x86_64/vmlinux DUMPFILE: /var/crash/127.0.0.1-2023-02-09-06:08:11/vmcore [PARTIAL DUMP] CPUS: 4 DATE: Thu Feb 9 20:07:56 JST 2023 UPTIME: 00:55:55 LOAD AVERAGE: 0.00, 0.03, 0.00 TASKS: 160 NODENAME: server RELEASE: 4.18.0-372.9.1.el8.x86_64 VERSION: #1 SMP Tue May 10 08:57:35 EDT 2022 MACHINE: x86_64 (2808 Mhz) MEMORY: 4 GB PANIC: "sysrq: SysRq : Trigger a crash" PID: 1489 COMMAND: "bash" TASK: ffff8f7fc1e50000 [THREAD_INFO: ffff8f7fc1e50000] CPU: 1 STATE: TASK_RUNNING (SYSRQ)
5 コマンド一覧、ヘルプを表示する方法(help)
5.1 コマンド一覧を表示する方法
引数なしでhelpを実行すると、コマンド一覧を表示することができます。
crash> help * files mod sbitmapq union alias foreach mount search vm ascii fuser net set vtop bpf gdb p sig waitq bt help ps struct whatis btop ipcs pte swap wr dev irq ptob sym q dis kmem ptov sys eval list rd task exit log repeat timer extend mach runq tree crash version: 7.3.2-2.el8.alma gdb version: 7.6 For help on any command above, enter "help <command>". For help on input options, enter "help input". For help on output options, enter "help output".
5.2 コマンドのヘルプを表示する方法
helpと入力したあとコマンド名を入力すると、コマンドのヘルプを表示することができます。
btコマンドのヘルプを表示してみます。
crash> help bt NAME bt - backtrace -snip-
次に、modコマンドのヘルプを表示してみます。
crash> help mod NAME mod - module information and loading of symbols and debugging data -snip-
6 logコマンドの使い方
logコマンドは、カーネルログバッファに保存されているログを表示するコマンドです。
6.1 引数無しで実行する方法
引数なしでlogコマンドを実行してみます。今回、SysRqによってカーネルパニックを発生させて、その時に生成したvmcoreを使って解析をしています。SysRqによるカーネルパニックが、カーネル起動後3354秒で発生していることがわかります。
crash> log [ 0.000000] Linux version 4.18.0-372.9.1.el8.x86_64 (mockbuild@142f1156fd3c4b36be0752fc556cdb86) (gcc version 8.5.0 20210514 (Red Hat 8.5.0-10) (GCC)) #1 SMP Tue May 10 08:57:35 EDT 2022 -snip- [ 3354.190163] sysrq: SysRq : Trigger a crash [ 3354.191105] Kernel panic - not syncing: sysrq triggered crash [ 3354.191753] CPU: 1 PID: 1489 Comm: bash Kdump: loaded Not tainted 4.18.0-372.9.1.el8.x86_64 #1 [ 3354.192081] Hardware name: Red Hat KVM/RHEL-AV, BIOS 1.15.0-2.module_el8.6.0+2880+7d9e3703 04/01/2014 [ 3354.192352] Call Trace: [ 3354.193123] dump_stack+0x41/0x60 [ 3354.193597] panic+0xe7/0x2ac [ 3354.193962] ? printk+0x58/0x6f [ 3354.194300] sysrq_handle_crash+0x11/0x20 [ 3354.194664] __handle_sysrq.cold.13+0x48/0xfb [ 3354.194977] write_sysrq_trigger+0x2b/0x30 [ 3354.195296] proc_reg_write+0x39/0x60 [ 3354.195654] vfs_write+0xa5/0x1a0 [ 3354.196018] ksys_write+0x4f/0xb0 [ 3354.196329] do_syscall_64+0x5b/0x1a0 [ 3354.196707] entry_SYSCALL_64_after_hwframe+0x65/0xca
6.2 時刻を表示する方法(-T)
-Tは時刻を表示するオプションです。カーネルの起動時刻が2023年2月9日 19時12分01秒であることがわかります。
crash> log -T [Thu Feb 9 19:12:01 JST 2023] Linux version 4.18.0-372.9.1.el8.x86_64 (mockbuild@142f1156fd3c4b36be0752fc556cdb86) (gcc version 8.5.0 20210514 (Red Hat 8.5.0-10) (GCC)) #1 SMP Tue May 10 08:57:35 EDT 2022 -snip-
6.3 ログの重要度を表示する方法(-m)
-mはログの重要度を表示するためのオプションです。重要度は、値が小さいほど重要度が高く、早急に処置が必要になります。以下は重要度の一覧です。
KERN_EMERG 0 KERN_ALERT 1 KERN_CRIT 2 KERN_ERR 3 KERN_WARNING 4 KERN_NOTICE 5 KERN_INFO 6 KERN_DEBUG 7
-mオプションを指定してlogコマンドを実行してみます。"Linux version..."の重要度はKERN_NOTICE(5)であることがわかります。一方、"Kernel panic.."の重要度はKERN_EMERG(0)であり、ただちに対処する必要があることがわかります。
crash> log -m [ 0.000000] <5>Linux version 4.18.0-372.9.1.el8.x86_64 (mockbuild@142f1156fd3c4b36be0752fc556cdb86) (gcc version 8.5.0 20210514 (Red Hat 8.5.0-10) (GCC)) #1 SMP Tue May 10 08:57:35 EDT 2022 -snip- [ 3354.191105] <0>Kernel panic - not syncing: sysrq triggered crash
7 setコマンドの使い方
setコマンドを使うことで、コンテキストを切り替えることができます。たとえば、コンテキストをsystemd(PIDが1)に切り替えたとします。このあとtaskコマンドを実行する場合、task 1と明にPIDを指定しなくても、taskと実行するだけでsystemdのtask_struct構造体の中身を表示することができます。taskコマンド以外でも、明にPIDを指定する必要がなくなります。
7.1 プロセスコンテキストを表示する方法
引数なしでsetコマンドを実行すると、現在実行中のプロセスコンテキストを表示します。
crash> set PID: 1489 COMMAND: "bash" TASK: ffff8f7fc1e50000 [THREAD_INFO: ffff8f7fc1e50000] CPU: 1 STATE: TASK_RUNNING (SYSRQ)
7.2 プロセスコンテキストを切り替える方法(set PID)
プロセスコンテキストをsystemdに切り替えます。プロセスコンテキストをsystemdに切り替えることで、この後で実行するコマンドにおいて、明にPIDを指定する必要がなくなります。
crash> set 1 PID: 1 COMMAND: "systemd" TASK: ffff8f7fc0bad000 [THREAD_INFO: ffff8f7fc0bad000] CPU: 0 STATE: TASK_INTERRUPTIBLE
7.3 表示画面のスクロールオフ・オンの切り替え方法(set scroll off/set scroll on)
デフォルトでは画面のスクロールがオンになっているので、crashコマンドの出力が1画面に収まらない場合は、スペースキーを押下して画面をスクロールする必要があります。
crash> set scroll off scroll: off (/usr/bin/less)
8 rdコマンドの使い方
rdコマンドはメモリの内容を表示するコマンドです。
8.1 メモリ内容を16進数/10進数(-d)で表示する方法
グローバル変数jiffiesの中身を表示してみます。jiffiesの値が0x1002e9d9bであることがわかります。jiffiesは、Linuxカーネルが起動してから定期的にカウントアップする変数です。
crash> rd jiffies ffffffff8dc06000: 00000001002e9d9b ........
jiffiesの中身を10進数で表示してみます。jiffiesの値が4298022299であることがわかります。
crash> rd -d jiffies ffffffff8dc06000: 4298022299
8.2 メモリ内容を文字列として表示する方法(-a)
メモリに格納されているASCII文字を表示してみます。
crash> rd -a linux_banner ffffffff8d200100: Linux version 4.18.0-372.9.1.el8.x86_64 (mockbuild@142f1156f ffffffff8d20013c: d3c4b36be0752fc556cdb86) (gcc version 8.5.0 20210514 (Red Ha ffffffff8d200178: t 8.5.0-10) (GCC)) #1 SMP Tue May 10 08:57:35 EDT 2022
9 modコマンドの使い方
modコマンドは、モジュールのロード/アンロードするコマンドです。
9.1 モジュール一覧を表示する方法
引数なしでmodコマンドを実行すると、モジュールの一覧が表示されます。以下の実行例では、モジュールがロードされていないので、"not loaded"と表示されています。
crash> mod MODULE NAME BASE SIZE OBJECT FILE ffffffffc033b080 failover ffffffffc0339000 16384 (not loaded) [CONFIG_KALLSYMS] ffffffffc0345040 net_failover ffffffffc0341000 24576 (not loaded) [CONFIG_KALLSYMS] ffffffffc0353440 virtio_console ffffffffc034c000 36864 (not loaded) [CONFIG_KALLSYMS] -snip-
9.2 モジュールを個別にロードする方法(-s)
-sはロードするモジュールを指定するオプションです。ここでは、failoverモジュールをロードしてみます。
crash> mod -s failover MODULE NAME BASE SIZE OBJECT FILE ffffffffc033b080 failover ffffffffc0339000 16384 /usr/lib/debug/lib/modules/4.18.0-372.9.1.el8.x86_64/kernel/net/core/failover.ko.debug
モジュールの一覧を確認します。OBJECT FILE欄にロードしたモジュールのファイル名が表示されているので、failoverモジュールがロードされたことがわかります。
crash> mod MODULE NAME BASE SIZE OBJECT FILE ffffffffc033b080 failover ffffffffc0339000 16384 /usr/lib/debug/lib/modules/4.18.0-372.9.1.el8.x86_64/kernel/net/core/failover.ko.debug -snip-
9.3 モジュールをアンロードする方法(-d)
-dはアンロードするモジュールを指定するオプションです。ここでは、failoverモジュールをアンロードしてみます。
crash> mod -d failover
モジュール一覧を確認します。OBJECT FILE欄が"not loaded"になっているため、failoverモジュールがアンロードされたことがわかります。
crash> mod MODULE NAME BASE SIZE OBJECT FILE ffffffffc033b080 failover ffffffffc0339000 16384 (not loaded) [CONFIG_KALLSYMS] -snip-
9.4 モジュールを一括でロードする方法(-S)
-Sは全てのモジュールを一括でロードするオプションです。モジュールを一括でロードします。
crash> mod -S
モジュール一覧を確認します。全てのモジュールがロードされたことがわかります。
crash> mod -S MODULE NAME BASE SIZE OBJECT FILE ffffffffc033b080 failover ffffffffc0339000 16384 /usr/lib/debug/lib/modules/4.18.0-372.9.1.el8.x86_64/kernel/net/core/failover.ko.debug ffffffffc0345040 net_failover ffffffffc0341000 24576 /usr/lib/debug/lib/modules/4.18.0-372.9.1.el8.x86_64/kernel/drivers/net/net_failover.ko.debug ffffffffc0353440 virtio_console ffffffffc034c000 36864 /usr/lib/debug/lib/modules/4.18.0-372.9.1.el8.x86_64/kernel/drivers/char/virtio_console.ko.debug -snip-
10 netコマンドの使い方
netコマンドは、ネットワークに関係する情報を表示するコマンドです。
10.1 net_device構造体を表示する方法
オプションなしでnetコマンドを実行すると、net_device構造体を表示することができます。net_device構造体は、NICの情報(NICの名前、NICの状態、IPアドレス(*)等)を保持するデータ構造です。以下の実行例では、loとeth0のnet_device構造体の先頭アドレス、名前、IPアドレスが表示されていることがわかります。
(*) 正確にはnet_device構造体がポイントするin_ifaddr構造体に格納されています。
crash> net NET_DEVICE NAME IP ADDRESS(ES) ffff8f7fc0e86000 lo 127.0.0.1 ffff8f7fc0e85000 eth0 192.168.122.68
10.2 arpキャッシュを表示する方法(-a)
-aはarpキャッシュを表示するオプションです。
crash> net -a NEIGHBOUR IP ADDRESS HW TYPE HW ADDRESS DEVICE STATE ffff8f7fc4ecf200 192.168.122.1 ETHER 52:54:00:02:06:f9 eth0 REACHABLE
10.3 プロセスが使用しているソケットの情報を表示する方法(-s)
-sはプロセスが使用しているソケットの情報を表示するオプションです。まず、psコマンドを実行して、sshdプロセスの状態を確認します。ここでは、sshdプロセスのソケットの情報を表示してみます。
crash> ps sshd PID PPID CPU TASK ST %MEM VSZ RSS COMM 842 1 2 ffff8f7fc2ec8000 IN 0.1 92408 7820 sshd 1471 842 2 ffff8f7fc4ee5000 IN 0.2 153500 10352 sshd 1488 1471 1 ffff8f7fc518d000 WA 0.1 153500 5908 sshd 1512 842 1 ffff8f7fd15d8000 IN 0.2 153500 10528 sshd 1516 1512 1 ffff8f7fc2c3d000 IN 0.1 153500 6100 sshd
sshd(PID=1471)が使用しているソケットの情報を表示してみます。sshdはソケットを5つ使用していて、それぞれ、FD(ファイルディスクリプタ)の5,6,7,9,12を使用していることがわかります。そして、1つはINETドメイン、残り4つはUNIXドメインのソケットであることがわかります。INETドメインのソケット情報では、192.168.122.68:22と192.168.122.1:42156の間でTCPコネクションが確立していることがわかります。
crash> net -s 1471 PID: 1471 TASK: ffff8f7fc4ee5000 CPU: 2 COMMAND: "sshd" FD SOCKET SOCK FAMILY:TYPE SOURCE-PORT DESTINATION-PORT 5 ffff8f7fd2877180 ffff8f7fc4d60000 INET:STREAM 192.168.122.68-22 192.168.122.1-42156 6 ffff8f7fc0421080 ffff8f7fc47a8d80 UNIX:STREAM 7 ffff8f7fd2851600 ffff8f7fc3760900 UNIX:DGRAM 9 ffff8f7fc0421b80 ffff8f7fc47aa400 UNIX:STREAM 12 ffff8f7fc4211340 ffff8f7fc47a8000 UNIX:STREAM
10.4 プロセスが使用しているソケットの詳細情報を表示する方法(-S)
-Sはプロセスが使用しているソケットの詳細情報を表示するオプションです。socket構造体の中身を表示することができます。
crash> net -S 1471 PID: 1471 TASK: ffff8f7fc4ee5000 CPU: 2 COMMAND: "sshd" FD SOCKET SOCK 5 ffff8f7fd2877180 ffff8f7fc4d60000 struct socket { state = SS_CONNECTED, type = 1, flags = 0, wq = 0xffff8f7fc2c8f880, file = 0xffff8f7fc4d11700, sk = 0xffff8f7fc4d60000, ops = 0xffffffff8d2fd3a0 } -snip-
10.5 10進/16進表記のIPアドレスをドット・デシマル形式に変換する方法(-N)
-Nは10進/16進表記のIPアドレスをドット・デシマル形式に変換するオプションです。netコマンドでsocket構造体を表示すると、saddrとdaddrというメンバがあります。このメンバには送信元IP、送信先IPアドレスが格納されていますが、IPアドレスが10進数で格納されているため、わかりずらいです。-Nオプションを使うことで理解しやすいドット・デシマル形式に変換することができます。
crash> net -S 1471 -snip- saddr = 1148889280, daddr = 24815808, -snip-
saddrをドット・デシマル形式に変換すると、送信元IPアドレスが192.168.122.68であることがわかります。
crash> net -N 1148889280 192.168.122.68
次にdaddrをドット・デシマルに変換すると、送信先IPアドレスが192.168.122.1であることがわかります。
crash> net -N 24815808 192.168.122.1
11 disコマンドの使い方
disコマンドは、逆アセンブルを表示するコマンドです。
11.1 逆アセンブルを表示する方法
ip_output()の逆アセンブルを表示してみます。
crash> dis ip_output 0xffffffff8cc7c780 <ip_output>: nopl 0x0(%rax,%rax,1) [FTRACE NOP] 0xffffffff8cc7c785 <ip_output+5>: push %r12 0xffffffff8cc7c787 <ip_output+7>: mov %rsi,%r12 -snip-
11.2 逆アセンブル表示とソースファイルの対比を表示する方法(-l)
-lは逆アセンブルとソースファイルを表示するオプションです。
crash> dis -l ip_output /usr/src/debug/kernel-4.18.0-372.9.1.el8/linux-4.18.0-372.9.1.el8.x86_64/net/ipv4/ip_output.c: 410 0xffffffff8cc7c780 <ip_output>: nopl 0x0(%rax,%rax,1) [FTRACE NOP] 0xffffffff8cc7c785 <ip_output+5>: push %r12 0xffffffff8cc7c787 <ip_output+7>: mov %rsi,%r12 0xffffffff8cc7c78a <ip_output+10>: push %rbp 0xffffffff8cc7c78b <ip_output+11>: mov %rdi,%rbp 0xffffffff8cc7c78e <ip_output+14>: push %rbx 0xffffffff8cc7c78f <ip_output+15>: mov %rdx,%rbx 0xffffffff8cc7c792 <ip_output+18>: sub $0x38,%rsp 0xffffffff8cc7c796 <ip_output+22>: mov 0x10(%rdx),%rsi 0xffffffff8cc7c79a <ip_output+26>: mov %gs:0x28,%rax 0xffffffff8cc7c7a3 <ip_output+35>: mov %rax,0x30(%rsp) 0xffffffff8cc7c7a8 <ip_output+40>: xor %eax,%eax /usr/src/debug/kernel-4.18.0-372.9.1.el8/linux-4.18.0-372.9.1.el8.x86_64/./include/linux/skbuff.h: 1003 0xffffffff8cc7c7aa <ip_output+42>: mov 0x58(%rdx),%rax 0xffffffff8cc7c7ae <ip_output+46>: and $0xfffffffffffffffe,%rax 0xffffffff8cc7c7b2 <ip_output+50>: mov (%rax),%rcx /usr/src/debug/kernel-4.18.0-372.9.1.el8/linux-4.18.0-372.9.1.el8.x86_64/net/ipv4/ip_output.c: 413 -snip-
11.3 ソースファイルを表示する方法(-s)
-sはソースファイルを表示するオプションです。-sには、シンボル名もしくは仮想アドレスを指定します。
シンボル名としてip_outputを指定してみます。ip_output()のソースコードが表示されたことがわかります。
crash> dis -s ip_output FILE: net/ipv4/ip_output.c LINE: 410 405 ip_finish_output, 406 !(IPCB(skb)->flags & IPSKB_REROUTED)); 407 } 408 409 int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb) * 410 { 411 struct net_device *dev = skb_dst(skb)->dev, *indev = skb->dev; 412 413 IP_UPD_PO_STATS(net, IPSTATS_MIB_OUT, skb->len); 414 415 skb->dev = dev; 416 skb->protocol = htons(ETH_P_IP); 417 418 return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, 419 net, sk, skb, indev, dev, 420 ip_finish_output, 421 !(IPCB(skb)->flags & IPSKB_REROUTED)); 422 } crash>
仮想アドレスとして0xffffffff8cc7c780を指定してみます。ip_output()のソースコードが表示されたことがわかります。
crash> dis -s 0xffffffff8cc7c780 FILE: net/ipv4/ip_output.c LINE: 410 405 ip_finish_output, 406 !(IPCB(skb)->flags & IPSKB_REROUTED)); 407 } 408 409 int ip_output(struct net *net, struct sock *sk, struct sk_buff *skb) * 410 { 411 struct net_device *dev = skb_dst(skb)->dev, *indev = skb->dev; 412 413 IP_UPD_PO_STATS(net, IPSTATS_MIB_OUT, skb->len); 414 415 skb->dev = dev; 416 skb->protocol = htons(ETH_P_IP); 417 418 return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, 419 net, sk, skb, indev, dev, 420 ip_finish_output, 421 !(IPCB(skb)->flags & IPSKB_REROUTED)); 422 } crash>
12 taskコマンドの使い方
taskコマンドは、task_struct構造体の情報を表示するコマンドです。task_struct構造体は、プロセスの名前、PID、状態等を保持するデータ構造です。
12.1 task_struct構造体の中身を表示する方法
PIDを指定してtaskコマンドを実行すると、PIDで指定したプロセスのtask_struct構造体の中身を表示することができます。
psコマンドを実行して、rsyslogdプロセスのPIDを確認します。PIDが1077であることがわかります。
crash> ps rsyslogd PID PPID CPU TASK ST %MEM VSZ RSS COMM 1077 1 2 ffff8f7fc37d5000 IN 0.1 215856 6804 rsyslogd
次に、rsyslogdのPIDを指定してtaskコマンドを実行します。
crash> task 1077 PID: 1077 TASK: ffff8f7fc37d5000 CPU: 2 COMMAND: "rsyslogd" struct task_struct { thread_info = { flags = 128, status = 0 }, -snip-
12.2 task_struct構造体のメンバの値を表示する方法(-R)
-Rは構造体のメンバの値を表示するオプションです。
rsyslogdのPIDを指定してtaskコマンドを実行します。このとき、-Rオプションにcommメンバ(プロセス名)を指定すると、プロセス名がrsyslogdであることがわかります。
crash> task 1077 -R comm PID: 1077 TASK: ffff8f7fc37d5000 CPU: 2 COMMAND: "rsyslogd" comm = "rsyslogd\000)\000\000\000\000\000",
-Rオプションにpidメンバの値を指定すると、PIDが1077であることがわかります。
crash> task 1077 -R pid PID: 1077 TASK: ffff8f7fc37d5000 CPU: 2 COMMAND: "rsyslogd" pid = 1077,
13 filesコマンドの使い方
filesコマンドは、プロセスがオープンしているファイルの情報を表示するコマンドです。
13.1 プロセスがオープンしているファイルの情報を表示する方法
PIDを指定して、rsyslogdがオープンしているファイルの情報を表示してみます。
crash> files 1077 PID: 1077 TASK: ffff8f7fc37d5000 CPU: 2 COMMAND: "rsyslogd" ROOT: / CWD: / FD FILE DENTRY INODE TYPE PATH 0 ffff8f7fc4aaa000 ffff8f7fc040b0c0 ffff8f7fc0e9eae8 CHR /dev/null 1 ffff8f7fc554a800 ffff8f7fc040b0c0 ffff8f7fc0e9eae8 CHR /dev/null 2 ffff8f7fc554a800 ffff8f7fc040b0c0 ffff8f7fc0e9eae8 CHR /dev/null 3 ffff8f7fc397d600 ffff8f7fc040b300 ffff8f7fc0e9c688 CHR /dev/urandom 4 ffff8f7fc2c72200 ffff8f7fd29fae40 ffff8f7fd28758f0 SOCK UNIX 5 ffff8f7fc3649600 ffff8f7fd29f9c00 ffff8f7fd2995a70 REG /var/log/messages 6 ffff8f7fc52e2700 ffff8f7fd29f9b40 ffff8f7fd29909b0 REG /var/log/secure 7 ffff8f7fc68b6600 ffff8f7fd2a09540 ffff8f7fc1409c30 UNKN inotify 8 ffff8f7fc4ab7e00 ffff8f7fc4001cc0 ffff8f7fd2992ff0 REG /var/log/cron 9 ffff8f7fc68b6000 ffff8f7fc172cf00 ffff8f7fc637adf0 REG /run/log/journal/971f5080a9c549438e6e9a21eeb90854/system.journal
13.2 プロセスがオープンしているファイルの情報を表示する方法
psコマンドを実行して、sshdプロセスのPIDを確認します。ここでは、PID1471 のsshdがオープンしているファイルの情報を表示してみます。
crash> ps sshd PID PPID CPU TASK ST %MEM VSZ RSS COMM 842 1 2 ffff8f7fc2ec8000 IN 0.1 92408 7820 sshd 1471 842 2 ffff8f7fc4ee5000 IN 0.2 153500 10352 sshd 1488 1471 1 ffff8f7fc518d000 WA 0.1 153500 5908 sshd 1512 842 1 ffff8f7fd15d8000 IN 0.2 153500 10528 sshd 1516 1512 1 ffff8f7fc2c3d000 IN 0.1 153500 6100 sshd
-RオプションにSOCKを指定してfilesコマンドを実行すると、sshdが使用しているソケットが表示されることがわかります。
crash> files 1471 -R SOCK PID: 1471 TASK: ffff8f7fc4ee5000 CPU: 2 COMMAND: "sshd" ROOT: / CWD: / FD FILE DENTRY INODE TYPE PATH 5 ffff8f7fc4d11700 ffff8f7fd29600c0 ffff8f7fd28771b0 SOCK TCP 6 ffff8f7fc62c3e00 ffff8f7fc43fda80 ffff8f7fc04210b0 SOCK UNIX 7 ffff8f7fc3649300 ffff8f7fd29d6600 ffff8f7fd2851630 SOCK UNIX 9 ffff8f7fc391eb00 ffff8f7fc43fd9c0 ffff8f7fc0421bb0 SOCK UNIX 12 ffff8f7fc4dbe200 ffff8f7fd2a67c00 ffff8f7fc4211370 SOCK UNIX
-RオプションにTCPを指定してfilesコマンドを実行すると、sshdが使用しているTCPソケットが表示されることがわかります。
crash> files 1471 -R TCP PID: 1471 TASK: ffff8f7fc4ee5000 CPU: 2 COMMAND: "sshd" ROOT: / CWD: / FD FILE DENTRY INODE TYPE PATH 5 ffff8f7fc4d11700 ffff8f7fd29600c0 ffff8f7fd28771b0 SOCK TCP
14 fuserコマンドの使い方
fuserコマンドは、ファイルやソケットを使用しているプロセスの情報を表示するコマンドです。
/var/log/messagesを使用しているプロセスの情報を表示してみます。rsyslogd、in:imjournal、rs:mainの3つのプロセスが/var/log/messagesを使用していることがわかります。
crash> fuser /var/log/messages PID TASK COMM USAGE 1077 ffff8f7fc37d5000 "rsyslogd" fd 1123 ffff8f7fc2c38000 "in:imjournal" fd 1129 ffff8f7fc2c3a800 "rs:main Q:Reg" fd
15 symコマンドの使い方
symコマンドは、シンボル情報を表示するコマンドです。
15.1 シンボル情報の一覧を表示する方法(-l)
シンボル情報の一覧を表示してみます。
crash> sym -l 0 (D) __per_cpu_start 0 (D) fixed_percpu_data 1000 (D) cpu_debug_store 2000 (D) irq_stack_backing_store 6000 (D) cpu_tss_rw 9000 (D) gdt_pag -snip-
15.2 モジュールに含まれるシンボル情報を表示する方法(-s)
failoverモジュールに含まれるシンボル情報を表示してみます。
crash> sym -m failover ffffffffc0339000 MODULE START: failover ffffffffc0339000 (t) failover_unregister ffffffffc0339090 (t) failover_get_bymac ffffffffc0339120 (t) failover_slave_unregister -snip-
15.3 特定の文字列を含むシンボル情報を表示する方法(-q)
ip_forwardという文字列を含むシンボル情報を表示してみます。
crash> sym -q ip_forward ffffffff8c814490 (t) selinux_ip_forward ffffffff8cc781f0 (t) ip_forward_finish ffffffff8cc78280 (T) ip_forward ffffffff8cc79b20 (T) ip_forward_options ffffffff8cc79cb4 (t) ip_forward_options.cold.8
なお、小文字tはstatic宣言をした関数を表します。static宣言をすると、他のファイルから参照できなくなります。
static int ip_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
一方、大文字Tはstatic宣言はしていないので、他のファイルから参照できます。
int ip_forward(struct sk_buff *skb)
15.4 シンボル情報の前後のシンボル情報を表示する方法(-p,-n)
ip_forwardの前にあるシンボル情報を表示してみます。ip_forwardの前にip_forward_finish が存在することがわかります。
crash> sym -p ip_forward ffffffff8cc781f0 (t) ip_forward_finish /usr/src/debug/kernel-4.18.0-372.9.1.el8/linux-4.18.0-372.9.1.el8.x86_64/net/ipv4/ip_forward.c: 66 ffffffff8cc78280 (T) ip_forward /usr/src/debug/kernel-4.18.0-372.9.1.el8/linux-4.18.0-372.9.1.el8.x86_64/net/ipv4/ip_forward.c: 87
ip_forwardの後にあるシンボル情報を表示してみます。ip_forwardの後にip_options_rcv_srr が存在することがわかります。
crash> sym -n ip_forward ffffffff8cc78280 (T) ip_forward /usr/src/debug/kernel-4.18.0-372.9.1.el8/linux-4.18.0-372.9.1.el8.x86_64/net/ipv4/ip_forward.c: 87 ffffffff8cc786f0 (T) ip_options_rcv_srr /usr/src/debug/kernel-4.18.0-372.9.1.el8/linux-4.18.0-372.9.1.el8.x86_64/net/ipv4/ip_options.c: 616
16 listコマンドの使い方
listコマンドは、単方向リストにつながっている構造体の情報を表示するコマンドです。
16.1 単方向リストにつながれたノードの情報を表示する方法
単方向リストにつながっているfile_system_type構造体メンバの値を表示してみます。file_system_type構造体は、ファイルシステムの情報を保持するデータ構造です。以下のように、グローバル変数file_systemsが単方向リストの先頭要素を示すポインタで、各file_system_type構造体が単方向リストにつながっています。ここでは、リスト先頭から末尾まで、file_system_type構造体メンバ(name,fs_flag)の値を表示してみます。
ffffffff8e09a5c0 file_system_type{} file_system_type{} file_systems --------------------> +--------------------+ +-------> +--------------------+ | *name | -> sysfs | | *name | -> rootfs +--------------------+ | +--------------------+ | fs_flags | -> 8 | | fs_flags | -> 0 +--------------------+ | +--------------------+ | | | | | +--------------------+ | +--------------------+ | *next | ----------+ | *next | -----> +--------------------+ +--------------------+ | | | | | | | | +--------------------+ +--------------------+
listコマンドを実行します。このとき-sオプションには、表示する構造体のメンバを指定します。ここでは、file_system_type構造体のnameとfs_flagsの値を指定しています。listコマンドの最後のパラメータには、リスト先頭のアドレスを指定します。実行結果を確認すると、リスト先頭がsysfs、その次がtmpfsであることがわかります。
crash> list file_system_type.next -s file_system_type.name,fs_flags ffffffff8e09a5c0 ffffffff8e09a5c0 name = 0xffffffff8d534245 "sysfs" fs_flags = 8 ffffffff8e05abe0 name = 0xffffffff8d55567f "tmpfs" fs_flags = 8 ffffffff8e086140 name = 0xffffffff8d504698 "bdev" fs_flags = 0 ffffffff8e09a200 name = 0xffffffff8d4eda8e "proc" fs_flags = 8 ffffffff8e0370a0 name = 0xffffffff8d4fc855 "cgroup" fs_flags = 8 -snip-
16.2 双方向リストにつながれた構造体の情報を表示する方法
双方向リストにつながれたtask_struct構造体のcommメンバ(プロセスの名前)の値を表示してみます。
task_struct構造体は、プロセスの名前や状態等を保持するデータ構造です。以下のように、task_struct構造体は双方向リストにつながれています。先頭はinit_taskグローバル変数で参照することができます。ここでは、task_struct構造体のcommメンバを先頭から末尾まで表示してみます。
ffffffff8dc18840 task_struct{} task_struct{} init_task-> +----------------+ +----------------+ | pid=0 | | pid=1 | +----------------+ +----------------+ | comm=swapper/0 | | comm=systemd | +----------------+ +----------------+ | | | | | | | | | | | | | list_head{} | | list_head{} | -*- +----------------+ <---+ +------> +----------------+ | | *next | ----|---+ | *next | -------> tasks +----------------+ | +----------------+ | | *prev | +----------- | *prev | -*- +----------------+ +----------------+ | | | | | | | | | | | | +----------------+ +----------------+
whatisコマンドでinit_taskの型を調べると、init_taskはtask_struct構造体であることがわかります。
crash> whatis init_task struct task_struct init_task;
init_task構造体の先頭アドレスを確認すると、0xffffffff8dc18840であることがわかります。
crash> rd init_task ffffffff8dc18840: 0000000080004000 .@......
listコマンドを実行します。このとき-hオプションには、双方向リスト先頭のアドレスを指定します。ここでは、双方向リスト先頭アドレスはffffffff8dc18840です。実行結果を確認すると、リスト先頭がswapper、その次がsystemdであることを確認することができます。
crash> list task_struct.tasks -s task_struct.comm -h ffffffff8dc18840 ffffffff8dc18840 comm = "swapper/0\000\000\000\000\000\000" ffff8f7fc0bad000 comm = "systemd\000\060\000\000\000\000\000\000" -snip-
17 treeコマンドの使い方
treeコマンドは、Radix treeやred-black treeにつながっている構造体の情報を表示するコマンドです。
17.1 確認に使うデータ
vmap_area構造体はメモリを管理するデータ構造です。以下のようにred-black treeにつながれています。"root"はrootノードを表しています。また、”l”はleft、"r"はrightを表しています。
(root) vmap_area{} ffff8f7fc0d30800 -> +---------------------+ | ulong va_start | +---------------------+ | ulong va_end | +---------------------+ | | rb_root{} | | +------------------+ | rb_node{} | vmap_area_root | ffff8f7fc0d30810 | ----> |+-------------------+| +------------------+ || __rb_parent_color || |+-------------------+| || *rb_right ||-+ |+-------------------+| | (root/l) +-|| *rb_left || | (root/r) vmap_area{} | |+-------------------+| | vmap_area{} ffff8f7fc001e8c0->+---------------------+ | | | | +---------------------+ <-ffff8f7fc7999c80 | | | | | | | | | | | | | | | | | | | +---------------------+ | | | | | | +---------------------+ | | | | rb_node{} | | | | rb_node{} | |+-------------------+|<-+ +->|+-------------------+| || __rb_parent_color || || __rb_parent_color || |+-------------------+| |+-------------------+| || *rb_right ||--+ || *rb_right ||---> |+-------------------+| | |+-------------------+| +--|| *rb_left || | <---|| *rb_left || | |+-------------------+| | |+-------------------+| (root/l/l) | | | | (root/l/r) | | vmap_area{} | | | | vmap_area{} | | +-------------+ | +---------------------+ | +-------------+ +---------------------+ | | | | | | |+-----------+|<+ +->|+-----------+| || rb_node{} || || rb_node{} || |+-----------+| |+-----------+| | | | | +-------------+ +-------------+
17.2 各ノードの位置を求める方法(-p)
パラメータ | 意味 |
---|---|
-t | ツリーのデータ構造を指定するオプションです。radix、xarray、rbtreeの3つを指定することができます。vmap_area構造体は、red-black treeにつながっているのでrbtreeを指定します |
-o | 左右ノードへのポインタを含むrb_node構造体メンバを指定するオプションです。なお、-oはrbtreeのみで指定できるオプションです |
-p | ノードの先頭アドレス、位置を表示するオプションです。位置とは(root/l)や(root/l/l)のことです。(root/l)はrootノードの一階層下の左側につながっている要素を表します。(root/l/l)はさらにもう一段下の左側につながっている要素を表します |
crash> tree -t rbtree -o vmap_area.rb_node vmap_area_root -p ffff8f7fc0d30800 position: root ffff8f7fc001e8c0 position: root/l ffff8f7fc001e740 position: root/l/l -snip-
17.3 各ノードのメンバの値を表示する方法(-s)
-sは各ノードのメンバの値を表示するオプションです。ここでは、vmap_area構造体のva_startメンバとva_endメンバの値を表示してみます。なお、-xは値を16進で表示するオプションです。-pはノードの位置を表示するオプションです。
crash> tree -t rbtree -o vmap_area.rb_node vmap_area_root -s vmap_area.va_start,va_end -xp ffff8f7fc0d30800 position: root va_start = 0xffff9f21809d0000 va_end = 0xffff9f21809d5000 ffff8f7fc001e8c0 position: root/l va_start = 0xffff9f21806e8000 va_end = 0xffff9f21806ed000 ffff8f7fc001e740 position: root/l/l va_start = 0xffff9f2180668000 va_end = 0xffff9f218066d000 -snip-
18 swapコマンドの使い方
swapコマンドは、スワップデバイスの情報を表示するコマンドです。
crash> swap SWAP_INFO_STRUCT TYPE SIZE USED PCT PRI FILENAME ffff8f7fc2af0000 PARTITION 262140k 0k 0% -2 /dev/vda2
19 repeatコマンドの使い方
repeatコマンドは、files等のコマンドを繰り返し実行したり、各コマンドの実行間隔を指定した秒数だけ遅らせることができるコマンドです。なお、repeatコマンドは、動作中のカーネルに対して実行します。
引数なしでcrashコマンドを実行します。引数なしでcrashコマンドを実行すると、動作中のカーネルの状態を確認することができます。
[root@server ~]# crash
setコマンドを実行して、スクロールをオフにします。
crash> set scroll off scroll: off (/usr/bin/less)
psコマンドを実行してchronydのPIDを求めます。chronydのPIDが505であることがわかります。
crash> ps chronyd PID PPID CPU TASK ST %MEM VSZ RSS COMM 785 1 3 ffff940386265000 IN 0.1 149124 5248 chronyd
setコマンドを実行して、コンテキストをchronydに変更します。
crash> set 785 PID: 785 COMMAND: "chronyd" TASK: ffff940386265000 [THREAD_INFO: ffff940386265000] CPU: 3 STATE: TASK_INTERRUPTIBLE
chronydがオープンしているファイルを2秒間隔で監視します。
crash> repeat -2 files PID: 785 TASK: ffff940386265000 CPU: 3 COMMAND: "chronyd" ROOT: / CWD: / FD FILE DENTRY INODE TYPE PATH 0 ffff94038523a300 ffff94038040b600 ffff940380eaf0f8 CHR /dev/null 1 ffff94038523a200 ffff94038040b600 ffff940380eaf0f8 CHR /dev/null 2 ffff94038523ab00 ffff94038040b600 ffff940380eaf0f8 CHR /dev/null 3 ffff94038523a700 ffff94038a410cc0 ffff94038a43ec30 SOCK UNIX 5 ffff940385d5e800 ffff940381423180 ffff94038a273430 REG /var/lib/sss/mc/passwd 6 ffff94038619ec00 ffff94038a566780 ffff940381740030 SOCK UDP 7 ffff94038619ed00 ffff94038a566c00 ffff940381741e70 SOCK UDPv6 8 ffff940381bc1b00 ffff94038a564600 ffff9403817f0870 SOCK UNIX PID: 785 TASK: ffff940386265000 CPU: 3 COMMAND: "chronyd" ROOT: / CWD: / FD FILE DENTRY INODE TYPE PATH 0 ffff94038523a300 ffff94038040b600 ffff940380eaf0f8 CHR /dev/null 1 ffff94038523a200 ffff94038040b600 ffff940380eaf0f8 CHR /dev/null 2 ffff94038523ab00 ffff94038040b600 ffff940380eaf0f8 CHR /dev/null 3 ffff94038523a700 ffff94038a410cc0 ffff94038a43ec30 SOCK UNIX 5 ffff940385d5e800 ffff940381423180 ffff94038a273430 REG /var/lib/sss/mc/passwd 6 ffff94038619ec00 ffff94038a566780 ffff940381740030 SOCK UDP 7 ffff94038619ed00 ffff94038a566c00 ffff940381741e70 SOCK UDPv6 8 ffff940381bc1b00 ffff94038a564600 ffff9403817f0870 SOCK UNIX -snip-
Z 参考情報
私が業務や記事執筆で参考にした書籍を以下のページに記載します。
Linux技術のスキルアップをしよう! - hana_shinのLinux技術ブログ