「coreファイルの取得」の編集履歴(バックアップ)一覧はこちら
coreファイルの取得 - (2010/05/01 (土) 23:44:25) の1つ前との変更点
追加された行は緑色になります。
削除された行は赤色になります。
coreファイルは、プログラムの異常(セグメンテーションフォルトなど)や、killコマンドなどにより、プログラムが特定のシグナルを受信した際に取得されます。
coreファイルに関しては[[man core>http://www.linux.or.jp/JM/html/LDP_man-pages/man5/core.5.html]]にいろいろ書いてあるので、そちらを見た方がよいのですが、ここでは単純にcoreとるために必要なことだけ書いて置きます。
**coreが取得されるシグナル
#region
以下はPOSIX.1-1990に定められたシグナルで、動作にCoreとあるシグナルを受信するとcoreが取得されます。
|CENTER:BGCOLOR(#EEE8AA):No|CENTER:BGCOLOR(#EEE8AA):シグナル名|CENTER:BGCOLOR(#EEE8AA):シグナル番号|CENTER:BGCOLOR(#EEE8AA):動作|CENTER:BGCOLOR(#EEE8AA):コメント|
|CENTER:1 |CENTER:SIGINT |CENTER:2 |CENTER:Term |CENTER:キーボードからの割り込み (Interrupt) |
|CENTER:2 |CENTER:SIGQUIT |CENTER:3 |CENTER:Core |CENTER:キーボードによる中止 (Quit) |
|CENTER:3 |CENTER:SIGILL |CENTER:4 |CENTER:Core |CENTER:不正な命令 |
|CENTER:4 |CENTER:SIGABRT |CENTER:6 |CENTER:Core |CENTER:abort(3) からの中断 (Abort) シグナル |
|CENTER:5 |CENTER:SIGFPE |CENTER:8 |CENTER:Core |CENTER:浮動小数点例外 |
|CENTER:6 |CENTER:SIGKILL |CENTER:9 |CENTER:Term |CENTER:Kill シグナル |
|CENTER:7 |CENTER:SIGSEGV |CENTER:11 |CENTER:Core |CENTER:不正なメモリ参照 |
|CENTER:8 |CENTER:SIGPIPE |CENTER:13 |CENTER:Term |CENTER:パイプ破壊: 読み手の無いパイプへの書き出し |
|CENTER:9 |CENTER:SIGALRM |CENTER:14 |CENTER:Term |CENTER:alarm(2) からのタイマーシグナル |
|CENTER:10|CENTER:SIGTERM |CENTER:15 |CENTER:Term |CENTER:終了 (termination) シグナル |
|CENTER:11|CENTER:SIGUSR1 |CENTER:10 |CENTER:Term |CENTER:ユーザ定義シグナル 1 |
|CENTER:12|CENTER:SIGUSR2 |CENTER:12 |CENTER:Term |CENTER:ユーザ定義シグナル 2 |
|CENTER:13|CENTER:SIGCHLD |CENTER:17 |CENTER:Ign |CENTER:子プロセスの一時停止 (stop) または終了 |
|CENTER:14|CENTER:SIGCONT |CENTER:18 |CENTER:Cont |CENTER:一時停止 (stop) からの再開 |
|CENTER:15|CENTER:SIGSTOP |CENTER:19 |CENTER:Stop |CENTER:プロセスの一時停止 (stop) |
|CENTER:16|CENTER:SIGTSTP |CENTER:20 |CENTER:Stop |CENTER:端末 (tty) より入力された一時停止 (stop) |
|CENTER:17|CENTER:SIGTTIN |CENTER:21 |CENTER:Stop |CENTER:バックグランドプロセスの tty 入力 |
|CENTER:18|CENTER:SIGTTOU |CENTER:22 |CENTER:Stop |CENTER:バックグランドプロセスの tty 出力 |
#endregion
**取得場所とファイル名
#region
coreが取得される場所は、受信したプログラムが動作しているカレントディレクトリです。
ファイル名は、通常は '&bold(){core}' もしくは '&bold(){core.<PID>}' という名称で取得されます。ファイル名は「&bold(){/proc/sys/kernel/core_pattern}」により変更可能です(詳細は[[man core>http://www.linux.or.jp/JM/html/LDP_man-pages/man5/core.5.html]]参照)。
#endregion
**core取得の制限サイズ
#region
coreファイルには取得サイズの制限値があり、ulimitコマンドで見ることができます。
>$ ulimit -a <ーーcoreサイズ以外も表示。coreのみ見たいときは ulimit -c
>core file size (blocks, -c) 0 <ーー1Kbyte単位。この例だと0Kbyte
> ・・・以下省略
上記の例だと0Kbyteのためcoreは取得されません。サイズ変更は、一時的に変更するなら以下のコマンドを実行します(実行したシェルとその子プロセスでのみ有効)。
>$ ulimit -c <サイズ> or $ ulimit -c unlimited ・・・後者は無限大とする
永続的に変更するには以下のファイルを修正します。
>/etc/security/limits.conf
#endregion
**coreの取得方法
#region
killコマンドを使う場合は、以下のようにします。
>$ kill -<動作がcoreのシグナル番号> <対象プロセスのPID>
ただし、このkillを使うと対象プロセスも終了してしまいます。終了させたくない場合は、gdbのgcoreコマンドを使います。
>$ gdb
>(gdb) attach <対象プロセスのPID>
>(gdb) gcore <ファイル名>
>(gdb) detach
これだと、人がコマンドをインタラクティブに入力しないといけないため、自動的にcoreを取得させるなどには使えません。
そのためRHELやCentOSでは、gdbのgcoreコマンドをshスクリプトで実装した&bold(){gcore}コマンドがあります。
>$ gcore
>usage: gcore [-o filename] pid
ディストリビューションによってgcoreコマンドがない場合があるので、[[gcoreコマンド]]にCentOS5.4のgcoreコマンドの内容を書いておきます。gdbがないことはないと思うので、どのディストリビューションでも使えると思います。
#endregion
** Google coredumper
#region
Google codeに[[coredumper>http://code.google.com/p/google-coredumper/]]というプロジェクトがあります。
gcoreのように、プロセスを止めずにcoreを取得するためのライブラリです。
shとは関係ありませんが、core取得ということでここに使いかたを書いておきます。
■インストール
[[http://code.google.com/p/google-coredumper/]]からダウンロードし、適当なところに展開します。試したときは &bold(){coredumper-1.2.1.tar.gz} が最新でした。
展開した中のINSTALLファイルにインストール方法がかかれていますが、Linuxの標準的なconfigure、make、make installのパターンでインストール可能です。
なお、以下のようにするとdebパッケージやrpmパッケージも作れるということで、make installはせずに、make rpm をして、rpmを作成してインストールしました。
>`make deb` - builds Debian packages
>`make rpm` - build RedHat RPM packages
rpmの作成先はmake rpmした際に表示されます。
>$ make rpm
> ・・・
>The rpm package file(s) are located in /home/test/Soft/develop/coredumper-1.2.1/packages/rpm-unknown
>$ ls /home/tomonari/Soft/develop/coredumper-1.2.1/packages/rpm-unknown
>coredumper-1.2.1-1.x86_64.rpm coredumper-devel-1.2.1-1.x86_64.rpm
>coredumper-debuginfo-1.2.1-1.x86_64.rpm
coredumperはライブラリであり、プログラムから呼び出すためにはヘッダファイルも必要なため、以下の2つをインストールしました。
>$ sudo rpm -ivh coredumper-1.2.1-1.x86_64.rpm
>$ ls /usr/lib/libcoredumper*
>/usr/lib/libcoredumper.a /usr/lib/libcoredumper.so.1
>/usr/lib/libcoredumper.la /usr/lib/libcoredumper.so.1.0.0
>/usr/lib/libcoredumper.so
>$ sudo rpm -ivh coredumper-devel-1.2.1-1.x86_64.rpm
>$ ls /usr/include/google
>coredumper.h
■使いかた
Webページに以下のように出ています。&bold(){coredumper.h}をincludeして、coreを取得したいところで&bold(){WriteCoreDump(coreファイル名)}とするだけですね。
>#include <google/coredumper.h>
> ...
> WriteCoreDump('core.myprogram');
> /* Keep going, we generated a core file,
> * but we didn't crash.
> */
■サンプル
ソース
>#include <stdio.h>
>#include <stdlib.h>
>#include <string.h>
>#include <errno.h>
>#include <google/coredumper.h>
>
>int main(){
> char *str;
> short svar;
> int ret,err;
>
> str = "Hello World";
> svar = 0x1234;
>
> ret = WriteCoreDump("core.test");
> err = errno;
> if ( ret == -1 ){
> strerror( err );
> exit(1);
> }
>
> printf("WriteCoreDump Success!! ret: %d\n",ret);
> exit(0);
>}
コンパイル・リンク
>$ gcc -o main main.c -lcoredumper -g <-- libcoredumperのリンクが必要、-gはgdbで変数の値をみるため
実行
>$ ./main
>WriteCoreDump Success!! ret: 0
>$ ls core.test
>core.test
>$ gdb -c core.test main <--本当にcore見られるか実験
> ・・・
>(gdb) bt
>#0 0x00002b9b483a5825 in WriteCoreDump () from /usr/lib/libcoredumper.so.1
>#1 0x0000000000400628 in main () at main.c:16
>(gdb) up
>#1 0x0000000000400628 in main () at main.c:16
>16 ret = WriteCoreDump("core.test");
>(gdb) p str
>$1 = 0x400768 "Hello World"
>(gdb) p /x svar
>$2 = 0x1234
なお、coredumperの[[ここ>http://code.google.com/p/google-coredumper/wiki/GetCoreDump]]とか[[ここ>http://code.google.com/p/google-coredumper/wiki/WriteCoreDump]]を見ると、APIの説明があります。core取得時に圧縮もできたりするようです。
#endregion
----
coreファイルは、プログラムの異常(セグメンテーションフォルトなど)や、killコマンドなどにより、プログラムが特定のシグナルを受信した際に取得されます。
coreファイルに関しては[[man core>http://www.linux.or.jp/JM/html/LDP_man-pages/man5/core.5.html]]にいろいろ書いてあるので、そちらを見た方がよいのですが、ここでは単純にcoreとるために必要なことだけ書いて置きます。
&color(red){※長くなったので、コンテンツをたたんで見出しを見えるようにしています。+をクリックして見てください。}
**coreが取得されるシグナル
#region
以下はPOSIX.1-1990に定められたシグナルで、動作にCoreとあるシグナルを受信するとcoreが取得されます。
|CENTER:BGCOLOR(#EEE8AA):No|CENTER:BGCOLOR(#EEE8AA):シグナル名|CENTER:BGCOLOR(#EEE8AA):シグナル番号|CENTER:BGCOLOR(#EEE8AA):動作|CENTER:BGCOLOR(#EEE8AA):コメント|
|CENTER:1 |CENTER:SIGINT |CENTER:2 |CENTER:Term |CENTER:キーボードからの割り込み (Interrupt) |
|CENTER:2 |CENTER:SIGQUIT |CENTER:3 |CENTER:Core |CENTER:キーボードによる中止 (Quit) |
|CENTER:3 |CENTER:SIGILL |CENTER:4 |CENTER:Core |CENTER:不正な命令 |
|CENTER:4 |CENTER:SIGABRT |CENTER:6 |CENTER:Core |CENTER:abort(3) からの中断 (Abort) シグナル |
|CENTER:5 |CENTER:SIGFPE |CENTER:8 |CENTER:Core |CENTER:浮動小数点例外 |
|CENTER:6 |CENTER:SIGKILL |CENTER:9 |CENTER:Term |CENTER:Kill シグナル |
|CENTER:7 |CENTER:SIGSEGV |CENTER:11 |CENTER:Core |CENTER:不正なメモリ参照 |
|CENTER:8 |CENTER:SIGPIPE |CENTER:13 |CENTER:Term |CENTER:パイプ破壊: 読み手の無いパイプへの書き出し |
|CENTER:9 |CENTER:SIGALRM |CENTER:14 |CENTER:Term |CENTER:alarm(2) からのタイマーシグナル |
|CENTER:10|CENTER:SIGTERM |CENTER:15 |CENTER:Term |CENTER:終了 (termination) シグナル |
|CENTER:11|CENTER:SIGUSR1 |CENTER:10 |CENTER:Term |CENTER:ユーザ定義シグナル 1 |
|CENTER:12|CENTER:SIGUSR2 |CENTER:12 |CENTER:Term |CENTER:ユーザ定義シグナル 2 |
|CENTER:13|CENTER:SIGCHLD |CENTER:17 |CENTER:Ign |CENTER:子プロセスの一時停止 (stop) または終了 |
|CENTER:14|CENTER:SIGCONT |CENTER:18 |CENTER:Cont |CENTER:一時停止 (stop) からの再開 |
|CENTER:15|CENTER:SIGSTOP |CENTER:19 |CENTER:Stop |CENTER:プロセスの一時停止 (stop) |
|CENTER:16|CENTER:SIGTSTP |CENTER:20 |CENTER:Stop |CENTER:端末 (tty) より入力された一時停止 (stop) |
|CENTER:17|CENTER:SIGTTIN |CENTER:21 |CENTER:Stop |CENTER:バックグランドプロセスの tty 入力 |
|CENTER:18|CENTER:SIGTTOU |CENTER:22 |CENTER:Stop |CENTER:バックグランドプロセスの tty 出力 |
#endregion
**取得場所とファイル名
#region
coreが取得される場所は、受信したプログラムが動作しているカレントディレクトリです。
ファイル名は、通常は '&bold(){core}' もしくは '&bold(){core.<PID>}' という名称で取得されます。ファイル名は「&bold(){/proc/sys/kernel/core_pattern}」により変更可能です(詳細は[[man core>http://www.linux.or.jp/JM/html/LDP_man-pages/man5/core.5.html]]参照)。
#endregion
**core取得の制限サイズ
#region
coreファイルには取得サイズの制限値があり、ulimitコマンドで見ることができます。
>$ ulimit -a <ーーcoreサイズ以外も表示。coreのみ見たいときは ulimit -c
>core file size (blocks, -c) 0 <ーー1Kbyte単位。この例だと0Kbyte
> ・・・以下省略
上記の例だと0Kbyteのためcoreは取得されません。サイズ変更は、一時的に変更するなら以下のコマンドを実行します(実行したシェルとその子プロセスでのみ有効)。
>$ ulimit -c <サイズ> or $ ulimit -c unlimited ・・・後者は無限大とする
永続的に変更するには以下のファイルを修正します。
>/etc/security/limits.conf
#endregion
**coreの取得方法
#region
killコマンドを使う場合は、以下のようにします。
>$ kill -<動作がcoreのシグナル番号> <対象プロセスのPID>
ただし、このkillを使うと対象プロセスも終了してしまいます。終了させたくない場合は、gdbのgcoreコマンドを使います。
>$ gdb
>(gdb) attach <対象プロセスのPID>
>(gdb) gcore <ファイル名>
>(gdb) detach
これだと、人がコマンドをインタラクティブに入力しないといけないため、自動的にcoreを取得させるなどには使えません。
そのためRHELやCentOSでは、gdbのgcoreコマンドをshスクリプトで実装した&bold(){gcore}コマンドがあります。
>$ gcore
>usage: gcore [-o filename] pid
ディストリビューションによってgcoreコマンドがない場合があるので、[[gcoreコマンド]]にCentOS5.4のgcoreコマンドの内容を書いておきます。gdbがないことはないと思うので、どのディストリビューションでも使えると思います。
#endregion
** Google coredumper
#region
Google codeに[[coredumper>http://code.google.com/p/google-coredumper/]]というプロジェクトがあります。
gcoreのように、プロセスを止めずにcoreを取得するためのライブラリです。
shとは関係ありませんが、core取得ということでここに使いかたを書いておきます。
■インストール
[[http://code.google.com/p/google-coredumper/]]からダウンロードし、適当なところに展開します。試したときは &bold(){coredumper-1.2.1.tar.gz} が最新でした。
展開した中のINSTALLファイルにインストール方法がかかれていますが、Linuxの標準的なconfigure、make、make installのパターンでインストール可能です。
なお、以下のようにするとdebパッケージやrpmパッケージも作れるということで、make installはせずに、make rpm をして、rpmを作成してインストールしました。
>`make deb` - builds Debian packages
>`make rpm` - build RedHat RPM packages
rpmの作成先はmake rpmした際に表示されます。
>$ make rpm
> ・・・
>The rpm package file(s) are located in /home/test/Soft/develop/coredumper-1.2.1/packages/rpm-unknown
>$ ls /home/tomonari/Soft/develop/coredumper-1.2.1/packages/rpm-unknown
>coredumper-1.2.1-1.x86_64.rpm coredumper-devel-1.2.1-1.x86_64.rpm
>coredumper-debuginfo-1.2.1-1.x86_64.rpm
coredumperはライブラリであり、プログラムから呼び出すためにはヘッダファイルも必要なため、以下の2つをインストールしました。
>$ sudo rpm -ivh coredumper-1.2.1-1.x86_64.rpm
>$ ls /usr/lib/libcoredumper*
>/usr/lib/libcoredumper.a /usr/lib/libcoredumper.so.1
>/usr/lib/libcoredumper.la /usr/lib/libcoredumper.so.1.0.0
>/usr/lib/libcoredumper.so
>$ sudo rpm -ivh coredumper-devel-1.2.1-1.x86_64.rpm
>$ ls /usr/include/google
>coredumper.h
■使いかた
Webページに以下のように出ています。&bold(){coredumper.h}をincludeして、coreを取得したいところで&bold(){WriteCoreDump(coreファイル名)}とするだけですね。
>#include <google/coredumper.h>
> ...
> WriteCoreDump('core.myprogram');
> /* Keep going, we generated a core file,
> * but we didn't crash.
> */
■サンプル
ソース
>#include <stdio.h>
>#include <stdlib.h>
>#include <string.h>
>#include <errno.h>
>#include <google/coredumper.h>
>
>int main(){
> char *str;
> short svar;
> int ret,err;
>
> str = "Hello World";
> svar = 0x1234;
>
> ret = WriteCoreDump("core.test");
> err = errno;
> if ( ret == -1 ){
> strerror( err );
> exit(1);
> }
>
> printf("WriteCoreDump Success!! ret: %d\n",ret);
> exit(0);
>}
コンパイル・リンク
>$ gcc -o main main.c -lcoredumper -g <-- libcoredumperのリンクが必要、-gはgdbで変数の値をみるため
実行
>$ ./main
>WriteCoreDump Success!! ret: 0
>$ ls core.test
>core.test
>$ gdb -c core.test main <--本当にcore見られるか実験
> ・・・
>(gdb) bt
>#0 0x00002b9b483a5825 in WriteCoreDump () from /usr/lib/libcoredumper.so.1
>#1 0x0000000000400628 in main () at main.c:16
>(gdb) up
>#1 0x0000000000400628 in main () at main.c:16
>16 ret = WriteCoreDump("core.test");
>(gdb) p str
>$1 = 0x400768 "Hello World"
>(gdb) p /x svar
>$2 = 0x1234
なお、coredumperの[[ここ>http://code.google.com/p/google-coredumper/wiki/GetCoreDump]]とか[[ここ>http://code.google.com/p/google-coredumper/wiki/WriteCoreDump]]を見ると、APIの説明があります。core取得時に圧縮もできたりするようです。
#endregion
----