在使用strace跟踪同一个文件时,出现了"execve文件未找到"的错误!

21

我认识的某个人在运行'lmutil'时遇到了问题,所以我让他执行'strace -f lmutil'。为什么execve失败并出现"找不到文件"的错误?!这没有任何意义,因为我正在跟踪同一个文件!!这里到底发生了什么???

strace -f /home/tabitha/Starprogram/FLEXlm_11.7/linux-x86_64-2.3.4/bin/lmutil

输出:

execve("/home/tabitha/Starprogram/FLEXlm_11.7/linux-x86_64-2.3.4/bin/lmutil", ["/home/tabitha/Starprogram/FLEXlm"...], [/* 38 vars */]) = -1 ENOENT (No such file or directory)
dup(2)                                  = 3
fcntl(3, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fd7cb8b0000
lseek(3, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
write(3, "strace: exec: No such file or di"..., 40strace: exec: No such file or directory
) = 40
close(3)                                = 0
munmap(0x7fd7cb8b0000, 4096)            = 0
exit_group(1)                           = ?

ldd 输出

$ ldd ./lmutil
        linux-vdso.so.1 =>  (0x00007fffcd5ff000)
        libpthread.so.0 => /lib/libpthread.so.0 (0x00007fe40ebbe000)
        libm.so.6 => /lib/libm.so.6 (0x00007fe40e93b000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007fe40e724000)
        libc.so.6 => /lib/libc.so.6 (0x00007fe40e3a1000)
        libdl.so.2 => /lib/libdl.so.2 (0x00007fe40e19d000)
        /lib64/ld-lsb-x86-64.so.3 => /lib64/ld-linux-x86-64.so.2 (0x00007fe40edf5000)
$ find . -name lmutil -exec file {} \;
./bin.linux.x86_64/lmutil: ELF 64-bit LSB 可执行文件, AMD x86-64,版本 1 (SYSV),用于GNU/Linux 2.4.0,动态链接(使用共享库),用于GNU/Linux 2.4.0,已剥离
./bin.linux.x86/lmutil: ELF 32-bit LSB 可执行文件,Intel 80386,版本 1 (SYSV),用于GNU/Linux 2.2.5,动态链接(使用共享库),用于GNU/Linux 2.2.5,已剥离
./lmutil: Bourne shell 脚本文本可执行文件

为了确保,ldd 输出是针对 …/linux-x86_64-2.3.4/bin/lmutil 的,对吗?这是什么操作系统(对于 Linux:什么发行版),什么版本和什么架构? - Gilles 'SO- stop being evil'
嗯...我不确定,现在他们正在尝试使用CentOS(Qemu)..操作系统是Linux,Ubuntu最新版本在AMD上(但我不完全确定),无论如何,我告诉他们仔细检查架构(32位vs 64位,intel / amd / sparc,linux / fbsd)以确保那不是问题所在。 - user621819
只是为了明确,我只想知道为什么strace会出现那个错误(文件未找到)...并不真正关心修复用户问题(让lmutil执行)。还要忽略“find . -name lmutil -exec file {} ;”和相关输出。对此表示歉意!显然,该命令并未由用户运行。但愿我能编辑掉它,但我不知道怎么做** - user621819
如果您没有编写lmutil,那么这不是与编程相关的问题,因此这里不是适当的讨论场所。我建议您请求迁移到Unix Stack Exchange - Gilles 'SO- stop being evil'
6个回答

19
您尝试执行的文件(…/lmutil)存在,但其“加载器”不存在。
  • 本地可执行文件的加载器是其动态加载器,例如/lib/ld-linux.so.2
  • 脚本的加载器是其在shebang行中提到的程序,例如,如果脚本以#!/bin/sh开头,则为/bin/sh
从目录名称来看,很有可能lmutil是一个amd64 Linux二进制文件,正在寻找/lib64/ld-linux-x86-64.so.2作为其加载器,但是您的amd64 Linux内核运行着386(即32位)用户空间。您需要获取适合您平台的二进制文件。
我认为这种情况是Unix最具误导性的错误消息。不幸的是,修复它很难:内核只能向程序的调用者报告数字错误代码,因此它只有“命令未找到”(ENOENT)的位置,而没有要查找的加载器的名称。这是strace无法帮助的罕见情况之一。

好的,库已经存在了 - ldd /whatever/lmutil 没有问题。它也是一个二进制文件 - file /whatever/lmutil。该软件包是用户在他的笔记本电脑上安装的,所以它不是一个远程文件系统。 - user621819
忽略 find . -name lmutil -exec file {} ;(该输出不是由用户生成的),这是一个错误,需要将其编辑删除。 - user621819
在Ubuntu 12.04上,您可以使用MultiArch,它允许您使用比老式的ia32-libs更多的库。请参阅https://help.ubuntu.com/community/MultiArch - Gilles 'SO- stop being evil'
如果内核报告缺少加载器错误时使用除ENOENT以外的其他内容仍然很有用。 - martinkunev
我遇到了同样的问题,这是由于二进制不兼容性问题引起的。这个答案非常有见地,即使没有更具体的日志! - undefined
显示剩余3条评论

6

您的ldd输出涉及到/lib64/ld-lsb-x86-64.so.3,但是这个加载器可能并不存在,除非(在Ubuntu上)您已经安装了lsb-core软件包。该软件包的postinst脚本会在/lib*目录中创建相关的符号链接。


这对我解决了问题: "ldd" 输出显示 "/lib64/ld-lsb-x86-64.so.3 => /lib64/ld-linux-x86-64.so.2",但我的系统(Ubuntu 16.04)上没有 "/lib64/ld-lsb-x86-64.so.3"。安装 "lsb-core" 包创建了此符号链接,然后 lmutil 就可以工作了。 - sheltond

3

纯属猜测,但我的第一个问题是,是否有这个问题的用户可以在没有strace的情况下运行可执行文件。此外,execve手册页指出,如果找不到文件或所需的脚本解释器或共享库,则会发生ENOENT。(我注意到这里涉及64位性。所有正确的库都可用吗?)

该文件是本地可执行文件还是可能是某种脚本?

这看起来像是一个许可证管理器 - 有没有可能它故意难以调试?

说到用户,'tabitha'是拥有可执行文件目录的用户吗?还是我们正在查看尝试通过其他普通用户安装程序而不是通过root以正常系统范围运行的可能复杂性?


如果操作系统无法运行它,strace也无法对其进行任何操作,这就是你在这里看到的情况。你可能需要检查该用户的读取和执行权限,然后再考虑库问题。 - Chris Stratton

2
您可以使用readelf(任何版本的readelf都可以,不需要来自特殊交叉编译器工具链的版本)来检查动态加载或可执行文件所需的加载程序。
$ readelf -l <filename> |grep -i interp
...
[Requesting program interpreter: /system/bin/linker]

提供一种可行的方法来调试ELF可执行文件,这是一个非常相关和自然的后续问题。虽然技术上回答了另一个问题,但它确实是一个很好的跟进问题。 - mtraceur

0

来自execve manpage:

成功时,execve() 不会返回任何值,出错时返回-1,并适当设置errno。

strace 假设 -1 表示“文件未找到”,因为 errnoENOENT-1,而 strace 没有区分。

因此,您可以忽略这个问题: -1 只是表示发生了一些错误。 strace 输出不告诉您 errno 的值。

我写这篇文章是为了警告大家不要轻易得出结论,即使在这种情况下 errno 也可能是 ENOENT


谢谢!还发现了这篇文章:http://people.redhat.com/alikins/old_docs/debug.txt - user621819
哦,这是一份好文档。而且如果正确的话,那就意味着我的答案是错误的。 :) - Lightness Races in Orbit
不,你误解了 strace 的输出。execve 返回 -1,而在调用 execveerrno 的值为 ENOENT - Gilles 'SO- stop being evil'
@Gilles:你好像没有看到我之前的评论。 - Lightness Races in Orbit
1
@Tomalak:如果你意识到你的答案是错误的,请编辑它以修正。说“我的答案是错误的”并不对读者有帮助:答案应该独立存在,即使他们阅读了评论,在我写这篇文章时,除非他们也阅读了我的评论,否则他们不会知道哪里出错了。 - Gilles 'SO- stop being evil'
显示剩余2条评论

0

您可以看到execve返回ENOENT。然后在execve man中搜索ENOENT。

文件路径名或脚本或ELF解释器不存在。

lmutil文件存在,是一个ELF文件。因此,请检查ELF解释器是否存在。根据手册:

如果可执行文件是动态链接的ELF可执行文件,则使用PT_INTERP段中命名的解释器来加载所需的共享对象。对于使用glibc链接的二进制文件,该解释器通常为/lib/ld-linux.so.2。

我们可以像@auselen所说的那样使用readelf找到ELF解释器路径:

$ readelf -l <filename> |grep -i interp
...
[Requesting program interpreter: /system/bin/linker]

ELF解释器不应该存在于此。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接