我正在尝试在具有多个用户的Linux服务器上运行ADB,但我不是root用户(以使用我的Android模拟器)。 adb 守护进程将其日志写入文件,/tmp/adb.log
不幸的是,该文件似乎被硬编码到 ADB 中,这种情况不会改变。
因此,adb 无法运行,并给出明显的错误:cannot open '/tmp/adb.log': Permission denied
。该文件是由另一个用户创建的,并且/tmp
具有粘滞位。如果我启动 adb 并将adb nodaemon server
其写入标准输出,则不会发生错误(我还将其端口设置为唯一值以避免冲突)。
我的问题是:有什么方法可以让 ADB 写入另一个文件吗/tmp/adb.log
?更一般地说,有没有办法创建一种特定于进程的符号链接?我想将所有文件访问重定向到/tmp/adb.log
file ~/tmp/adb.log
。
再次强调,我不是服务器上的 root 用户,因此chroot
、mount -o rbind
和chmod
不是有效的选项。如果可能的话,我不想修改 ADB 源代码,但如果没有其他解决方案,我肯定会这样做。
PS 对于特定的 ADB 情况,我可以诉诸于运行adb nodaemon server
和nohup
输出重定向,但一般问题仍然相关。
答案1
LD_PRELOAD 并不太难,而且您不需要是 root。插入您自己的 C 例程,该例程将被调用,而不是open()
C 库中的实际例程。您的例程检查要打开的文件是否为“/tmp/adb.log”,并使用不同的文件名调用真正的打开。这是你的 shim_open.c:
/*
* capture calls to a routine and replace with your code
* gcc -Wall -O2 -fpic -shared -ldl -o shim_open.so shim_open.c
* LD_PRELOAD=/.../shim_open.so cat /tmp/adb.log
*/
#define _FCNTL_H 1 /* hack for open() prototype */
#define _GNU_SOURCE /* needed to get RTLD_NEXT defined in dlfcn.h */
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#define OLDNAME "/tmp/adb.log"
#define NEWNAME "/tmp/myadb.log"
int open(const char *pathname, int flags, mode_t mode){
static int (*real_open)(const char *pathname, int flags, mode_t mode) = NULL;
if (!real_open) {
real_open = dlsym(RTLD_NEXT, "open");
char *error = dlerror();
if (error != NULL) {
fprintf(stderr, "%s\n", error);
exit(1);
}
}
if (strcmp(pathname,OLDNAME)==0) pathname = NEWNAME;
fprintf(stderr, "opening: %s\n", pathname);
return real_open(pathname, flags, mode);
}
编译它gcc -Wall -O2 -fpic -shared -ldl -o shim_open.so shim_open.c
并通过放入一些东西/tmp/myadb.log
并运行来 测试它LD_PRELOAD=/.../shim_open.so cat /tmp/adb.log
。然后尝试 adb 上的 LD_PRELOAD。
答案2
这是一个非常简单的示例,使用util-linux
'sunshare
将进程放入私有挂载命名空间中,并为其父进程当前拥有的同一文件系统提供不同的视图:
{ cd /tmp #usually a safe place for this stuff
echo hey >file #some
echo there >file2 #evidence
sudo unshare -m sh -c ' #unshare requires root by default
mount -B file2 file #bind mount there over hey
cat file #show it
kill -TSTP "$$" #suspend root shell and switch back to parent
umount file #unbind there
cat file' #show it
cat file #root shell just suspended
fg #bring it back
cat file2 #round it off
}
there #root shell
hey #root shell suspended
hey #root shell restored
there #rounded
unshare
尽管挂载命名空间工具本身对于整个 3.x 内核系列来说已经相当成熟,但您可以使用最新 Linux 系统上的实用程序为进程提供其文件系统的私有视图。您可以使用同一包中的实用程序输入各种预先存在的命名空间nsenter
,并且可以使用man
.