当前位置: 首页 > 面试题库 >

如何在Linux中检测文件访问?

卢景澄
2023-03-14
问题内容

我有一堆偶尔需要监视的流和数据处理应用程序,这意味着我需要知道它们读取了哪些文件。这主要是帮助打包测试用例,但在调试时也很有用。

有没有一种方法可以生成这样的列表来运行可执行文件?

我对此有两个想法:

  1. 我可以调用一个命令,该命令将调用我的应用程序。与GDB相似的东西。我叫GDB,给它一个指向可执行文件的路径,并提供一些参数,GDB为我调用了它。也许有些事情告诉我如何使用系统资源。
  2. 也许更有趣(但不必要的旁路)解决方案。
    1. 创建一个名为libc.so的库,该库实现了fopen(以及其他一些方法)
    2. 更改LD_LIBRARY_PATH以指向新库
    3. 复制真正的libc.so并在编辑器中重命名fopen(也许是nepof)
    4. 我的库加载了副本并根据需要调用重命名的函数以提供fopen功能。
    5. 调用应用程序,然后调用我的代理服务器fopen。

替代方案1当然是更可取的方案,但也欢迎就如何更轻松地进行方案2提出意见。


问题答案:

一种选择是使用strace:

strace -o logfile -eopen yourapp

这将记录所有文件打开事件,但会造成性能上的重大下降。但是,它具有易于使用的优点。

另一种选择是使用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

并使用以下代码运行您的程序:

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

这样的开销要少得多。

但是请注意,还有其他用于打开文件的入口点-例如,fopen(),openat()或许多旧版兼容性入口点之一:

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
,因为LD_PRELOAD库不会钩挂从fopen()到open()的libc内部调用。

类似的警告适用于strace-也有“
openat”html" target="_blank">系统调用,并且根据您的体系结构,可能还会有其他旧系统调用。但是不如LD_PRELOAD挂钩那么多,因此,如果您不介意性能下降,它可能是一个更简单的选择。



 类似资料:
  • 问题内容: 在我的项目中,我具有文件上传功能。文件通过FTP上传。我需要配置一个侦听器,该侦听器将检查新文件并仅在文件上传完成后才调用脚本。因为如果我在检测到新文件后立即运行此脚本,它将开始处理未完全上载的文件,这将导致错误。谁能说出这在LINUX上是否可行,我该怎么做? 问题答案: 我会尝试使用inotify,事件代码为IN_CLOSE_WRITE。

  • 问题内容: 我有一个网站,并且在我的本地主机上运行良好。 在Godaddy托管上上传后,我的网络出现了错误。结论是,我必须更改php.ini文件上的memory_limit,但无法在FTP管理器上找到php.ini。 我试图: 找到更改为“分类FTP”管理器的方法。 从本地创建/上传php.ini文件,但不起作用。 我的问题是:我该如何解决?我必须更改php.ini文件。有人有像我这样的经历吗?

  • 我正在尝试自动化电子邮件注册。当我手动操作时,它会工作,但当我用selenium打开网站时,它不会工作。它有我不能做的验证。有没有一种方法可以在不被检测的情况下打开(而不是控制,我使用pyautogui)一个网站? 我的代码:

  • 是否有一种方法可以在每次文件更改时以某种方式触发一个事件?我是指类似的东西(在伪代码中) 我知道我可以周期性地做,但我能在没有计时器的情况下做吗?我希望在用户更新txt文件时(不是通过代码,而是通过打开文件并在里面写入)能够做出一些动作,但我不知道他什么时候会这么做。

  • !define MUI_PAGE_CUSTOMFUNCTION_LEAVE DirectoryLeave !insertmacro MUI_PAGE_DIRECTORY Function DirectoryLeave IfFileExists "$INSTDIR\*.*" 0 +3 MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \ "The desti

  • 但我进的是空异常。有什么问题,有人能帮忙吗?