Linux下如何实时别名/重命名文件?解决应用写入同名配置文件难题
Hey Axel, this is a tricky but common problem when dealing with unmodifiable legacy apps—symlinks don't cut it here because they leave that unwanted samename.cfg visible, so let's dive into three solid solutions that fit your needs:
samename.cfg残留) 1. LD_PRELOAD 函数拦截(最灵活,无需root)
This method injects a custom shared library into the app's process to intercept file system calls, redirecting all requests for samename.cfg to anothername.cfg without touching the actual directory structure. No samename.cfg will ever exist in the target directories.
步骤:
- Write a simple C library (save as
redirect_cfg.c):
#define _GNU_SOURCE #include <dlfcn.h> #include <stdio.h> #include <string.h> // Pointer to the original open function int (*original_open)(const char*, int, mode_t) = NULL; // Override the open function int open(const char *pathname, int flags, mode_t mode) { char new_path[1024]; strncpy(new_path, pathname, sizeof(new_path)-1); new_path[sizeof(new_path)-1] = '\0'; // Swap samename.cfg with anothername.cfg char *cfg_name = strstr(new_path, "samename.cfg"); if (cfg_name) { strncpy(cfg_name, "anothername.cfg", strlen("anothername.cfg")); pathname = new_path; } // Load and call the original open function if (!original_open) { original_open = dlsym(RTLD_NEXT, "open"); } return original_open(pathname, flags, mode); } // Also handle openat (used by most modern apps) int openat(int dirfd, const char *pathname, int flags, mode_t mode) { static int (*original_openat)(int, const char*, int, mode_t) = NULL; char new_path[1024]; strncpy(new_path, pathname, sizeof(new_path)-1); new_path[sizeof(new_path)-1] = '\0'; char *cfg_name = strstr(new_path, "samename.cfg"); if (cfg_name) { strncpy(cfg_name, "anothername.cfg", strlen("anothername.cfg")); pathname = new_path; } if (!original_openat) { original_openat = dlsym(RTLD_NEXT, "openat"); } return original_openat(dirfd, pathname, flags, mode); }
- Compile it into a shared library:
gcc -shared -fPIC -o libredirect_cfg.so redirect_cfg.c -ldl
- Run your app with the library preloaded:
LD_PRELOAD=/full/path/to/libredirect_cfg.so /path/to/your/application
Pro tip: If you need this to apply automatically whenever the app runs, add the LD_PRELOAD line to the app's startup script or the user's ~/.bashrc (if running as a regular user).
2. Bind Mount(系统级重定向,需root)
Bind mounting lets you map one file to another at the filesystem level. While you'll temporarily create a samename.cfg file as the mount point, you can delete it after mounting—leaving no trace of it in the directory, while the app still thinks it's accessing the original file.
步骤:
- First, create your target config file if it doesn't exist:
touch /path/to/target/dir/anothername.cfg
- Create a temporary
samename.cfgas the mount point:
touch /path/to/target/dir/samename.cfg
- Bind the real config to the temporary file:
sudo mount --bind /path/to/target/dir/anothername.cfg /path/to/target/dir/samename.cfg
- Now you can delete the temporary
samename.cfg—the mount will remain active, and the directory will only showanothername.cfg:
rm /path/to/target/dir/samename.cfg
- To make this persistent across reboots, add a line to
/etc/fstab:
/path/to/target/dir/anothername.cfg /path/to/target/dir/samename.cfg none bind 0 0
Note: You'll need to repeat this for every directory where the app writes the config.
3. eBPF 内核级拦截(高级方案)
For power users, eBPF can intercept filesystem operations at the kernel level and rewrite the filename before it reaches the disk. This offers system-wide control without modifying processes or mount points, but it requires familiarity with eBPF tools like bcc or libbpf. It's a great choice if you need to handle dozens of directories or want a fully invisible solution.
内容的提问来源于stack exchange,提问作者Axel Booltink




