2009-05-18 30 views
10

私は時にはスパイする必要があるフローとデータ処理アプリケーションをたくさん持っています。つまり、どのファイルが読み込まれているかを知る必要があります。これは主にテストケースのパッケージングを支援することですが、デバッグ時にも役立ちます。Linuxでファイルアクセスを検出するにはどうすればよいですか?

このようなリストを生成するような方法で実行可能ファイルを実行する方法はありますか?

私はこの上に2つの考えがあります。

  1. は、私が呼び出すことができるコマンドがありますが、そのコマンドが私のアプリを起動します。 GDBのラインに沿った何か。私はGDBを呼び出し、実行可能ファイルへのパスといくつかの引数を与え、GDBはそれを私のために呼び出します。おそらく、システムリソースがどのように使われているかを教えてくれるようなものがあります。
  2. おそらくもっと興味深い(ただし、不要なサイドパス)解決策です。
    1. はlibc.soが(おそらく、nepof)のfopenを実際のlibc.soのコピーを作成し、名前を変更し、新しいライブラリ
    2. を指すようにはfopen(およびいくつかの他)
    3. 変更LD_LIBRARY_PATHを実装と呼ばれるライブラリを作成しますエディタで
    4. 私のライブラリはコピーをロードし、必要に応じて名前を変更した関数を呼び出して、機能を提供します。
    5. 私のプロキシfopenを呼び出すアプリケーションを呼び出します。

代替#1は確かに望ましいものであろうが、より簡単に#2を行う方法についてのコメントは、あまりにも歓迎されています。

+0

も参照してください。http://stackoverflow.com/q/2972765/119790 –

答えて

13

1つのオプションは、straceのを使用することです:

strace -o logfile -eopen yourapp 

これは、すべてのファイルを開くイベントをログに記録しますが、それは意志重要なパフォーマンスペナルティを課すことがあります。しかし、それは使いやすいという利点があります。

もう1つのオプションは、LD_PRELOADを使用することです。これはあなたのオプション#2に相当します。

#define _GNU_SOURCE 
#include <stdio.h> 
#include <dlfcn.h> 

int open(const char *fn, int flags) { 
    static int (*real_open)(const char *fn, int flags); 

    if (!real_open) { 
     real_open = dlsym(RTLD_NEXT, "open"); 
    } 

    fprintf(stderr, "opened file '%s'\n", fn); 
    return real_open(fn, flags); 
} 

その後でビルド:

gcc -fPIC -shared -ldl -o preload-example.so preload-example.c 

とEGを使用してプログラムを実行します。

$ LD_PRELOAD=$PWD/preload-example.so cat /dev/null 
opened file '/dev/null' 

これは、はるかに少ないオーバーヘッドを持っている基本的な考え方は、このような何かを行うことです。

ただし、ファイルを開くための他のエントリポイントがあること - )(openat、例えば、はfopen()、または多くのレガシー互換性のエントリポイントの1:

00000000000747d0 g DF .text  000000000000071c GLIBC_2.2.5 _IO_file_fopen 
0000000000068850 g DF .text  000000000000000a GLIBC_2.2.5 fopen 
000000000006fe60 g DF .text  00000000000000e2 GLIBC_2.4 open_wmemstream 
00000000001209c0 w DF .text  00000000000000ec GLIBC_2.2.5 posix_openpt 
0000000000069e50 g DF .text  00000000000003fb GLIBC_2.2.5 _IO_proc_open 
00000000000dcf70 g DF .text  0000000000000021 GLIBC_2.7 __open64_2 
0000000000068a10 g DF .text  00000000000000f5 GLIBC_2.2.5 fopencookie 
000000000006a250 g DF .text  000000000000009b GLIBC_2.2.5 popen 
00000000000d7b10 w DF .text  0000000000000080 GLIBC_2.2.5 __open64 
0000000000068850 g DF .text  000000000000000a GLIBC_2.2.5 _IO_fopen 
00000000000d7e70 w DF .text  0000000000000020 GLIBC_2.7 __openat64_2 
00000000000e1ef0 g DF .text  000000000000005b GLIBC_2.2.5 openlog 
00000000000d7b10 w DF .text  0000000000000080 GLIBC_2.2.5 open64 
0000000000370c10 g DO .bss  0000000000000008 GLIBC_PRIVATE _dl_open_hook 
0000000000031680 g DF .text  0000000000000240 GLIBC_2.2.5 catopen 
000000000006a250 g DF .text  000000000000009b GLIBC_2.2.5 _IO_popen 
0000000000071af0 g DF .text  000000000000026a GLIBC_2.2.5 freopen64 
00000000000723a0 g DF .text  0000000000000183 GLIBC_2.2.5 fmemopen 
00000000000a44f0 w DF .text  0000000000000088 GLIBC_2.4 fdopendir 
00000000000d7e70 g DF .text  0000000000000020 GLIBC_2.7 __openat_2 
00000000000a3d00 w DF .text  0000000000000095 GLIBC_2.2.5 opendir 
00000000000dcf40 g DF .text  0000000000000021 GLIBC_2.7 __open_2 
00000000000d7b10 w DF .text  0000000000000080 GLIBC_2.2.5 __open 
0000000000074370 g DF .text  00000000000000d7 GLIBC_2.2.5 _IO_file_open 
0000000000070b40 g DF .text  00000000000000d2 GLIBC_2.2.5 open_memstream 
0000000000070450 g DF .text  0000000000000272 GLIBC_2.2.5 freopen 
00000000000318c0 g DF .text  00000000000008c4 GLIBC_PRIVATE __open_catalog 
00000000000d7b10 w DF .text  0000000000000080 GLIBC_2.2.5 open 
0000000000067e80 g DF .text  0000000000000332 GLIBC_2.2.5 fdopen 
000000000001e9b0 g DF .text  00000000000003f5 GLIBC_2.2.5 iconv_open 
00000000000daca0 g DF .text  000000000000067b GLIBC_2.2.5 fts_open 
00000000000d7d60 w DF .text  0000000000000109 GLIBC_2.4 openat 
0000000000068850 w DF .text  000000000000000a GLIBC_2.2.5 fopen64 
00000000000d7d60 w DF .text  0000000000000109 GLIBC_2.4 openat64 
00000000000d6490 g DF .text  00000000000000b6 GLIBC_2.2.5 posix_spawn_file_actions_addopen 
0000000000121b80 g DF .text  000000000000008a GLIBC_PRIVATE __libc_dlopen_mode 
0000000000067e80 g DF .text  0000000000000332 GLIBC_2.2.5 _IO_fdopen 

あなたがフックする必要があるかもしれませんがこれらのすべては完全性のために - 少なくとも接頭辞なしのものはフックされるべきです。特に、fopen()からopen()へのlibc-internal呼び出しはLD_PRELOADライブラリによってフックされないので、を別途フックする必要があります。

同様の警告がstraceにも当てはまります - 'openat'のシステムコールもありますが、アーキテクチャにもよりますが、他のレガシーシステムコールもあるかもしれません。しかし、LD_PRELOADフックと同じくらい多くはないので、パフォーマンスが低下するのを気にしないなら、より簡単なオプションかもしれません。プログラムが開かれたすべてのファイルのリストを取得するには、その後

strace -o file.txt ./command 

あなたはできる

cat file.txt | grep open 

4
man strace 

例(2343年は、プロセスIDであると仮定):

# logging part 
strace -p 2343 -ff -o strace_log.txt 

# displaying part 
grep ^open strace_log.txt 
2

私は何を使用するようなものです。

関連する問題