如果动态链接失败,我会收到此错误:
/ # /manager
/bin/sh: /manager: not found
对于普通用户来说,这非常令人困惑,因为
/manager
存在。
现在,经过几个小时的搜索,我发现我可以像这样调试它以获得更好的错误消息:
> / # ldd /manager
/lib64/ld-linux-x86-64.so.2 (0x7f6f93f09000)
Error loading shared library libresolv.so.2: No such file or directory (needed by /manager)
libpthread.so.0 => /lib64/ld-linux-x86-64.so.2 (0x7f6f93f09000)
libc.so.6 => /lib64/ld-linux-x86-64.so.2 (0x7f6f93f09000)
我想要更好的错误消息。
类似:
/ # /manager
/bin/sh: /manager: Error loading shared library libresolv.so.2: No such file or directory (needed by /manager)
如果这是不可能的,那么通用错误消息会很好:
/ # /manager
/bin/sh: /manager: loading a shared library failed.
这将帮助这个星球上的很多人。
现在我向内核专家提出问题:
是否可以在相关源代码中打补丁,以便将来用户得到更好的错误消息?
这是一个基于alpine的容器镜像。
子问题:相关源码在哪里?
错误代码
ENOENT
,对应于消息 not found
,通过 execve(2)
系统调用直接来自内核。从手册页:
艾诺特
文件名或脚本或ELF解释器不存在,或找不到文件所需的共享库或解释器。
它无法在内核级别或 libc 级别“修复”,因为这会破坏众所周知的接口。
如果 shell 是 Bash,则在从文件
execve(2)
中名为 shell_execve()
的函数调用 execute_cmd.c
后,它会向您显示此消息。一些相关代码:
execve (command, args, env);
i = errno; /* this would be ENOENT */
if (executable_file (command) == 0)
{
errno = i;
file_error (command); /* No such file or directory */
}
else if (i == ENOENT)
{
errno = i;
internal_error (_("%s: cannot execute: required file not found"), command);
}
修补和包含更好消息的最佳位置就在那里。
Bash 已经尝试改进该消息。如果该文件不存在,则消息将为“没有这样的文件或目录”。当文件存在并且可执行时,消息将更改为“找不到所需的文件”,这更接近您想要的。如果所需的文件是解释器,则消息将更改为“错误的解释器”。
因此,您可以在现有消息中添加“使用 ldd 检查所有动态库是否存在”。要知道哪个库,您需要从
ldd(1)
获取一些代码。
我不知道你的 shell 是什么,但旧版本的 Bash 只会返回“没有这样的文件或目录”,正如你所得到的。