Execve file не найден, когда стягивает тот же самый файл!

Кто-то, кого я знаю, столкнулся с проблемой при запуске '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 output

$ 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 executable, AMD x86-64, version 1 (SYSV), for GNU/Linux 2.4.0, dynamically linked (uses shared libs), for GNU/Linux 2.4.0, stripped
./bin.linux.x86/lmutil: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.2.5, dynamically linked (uses shared libs), for GNU/Linux 2.2.5, stripped
./lmutil: Bourne shell script text executable

Ответы

Ответ 1

Файл, который вы пытаетесь выполнить (…/lmutil) существует, но его "загрузчик" не существует, где

  • загрузчиком исполняемого файла является его динамический загрузчик, например /lib/ld-linux.so.2;
  • загрузчик script - это программа, упомянутая в его строке shebang, например, /bin/sh, если script начинается с #!/bin/sh.

Из имени каталога есть хорошая вероятность, что lmutil является двоичным файлом amd64 Linux, ища /lib64/ld-linux-x86-64.so.2 в качестве своего загрузчика, но у вас есть ядро ​​amd64 Linux, на котором запущено 386 (то есть 32-разрядное) пользовательское пространство, Вам нужно получить подходящие файлы для вашей платформы.

Я рассматриваю эту ситуацию как самое ошибочное сообщение об ошибке Unix. К сожалению, исправление было бы затруднительным: ядро ​​может сообщать вызывающему абоненту код с числовой ошибкой, поэтому у него есть только место для "command not found" (ENOENT), а не для имени загрузчика, который он ищет, Это один из таких редких случаев, когда strace не помогает.

Ответ 2

Ваш вывод ldd относится к /lib 64/ld-lsb-x86-64.so.3, но этот загрузчик может не существовать, если только (на Ubuntu) вы не установили пакет lsb-core. Postinst script для пакета создает соответствующие символические ссылки в каталогах /lib *.

Ответ 3

Просто немного спекуляций, но мой первый вопрос был бы, если пользователь, который имеет эту проблему, может запустить исполняемый файл сам по себе без ограничений.

Также на странице руководства execve указано, что ENOENT будет возникать, если невозможно найти файл или требуемую интерпретатор script или общую библиотеку. (Я замечаю, что здесь задействована 64-разрядная версия. Доступны ли все доступные библиотеки?)

Является ли файл родным исполняемым файлом или может быть каким-то script?

Это похоже на менеджера по лицензированию - любой шанс, который он сделал намеренно трудно отлаживать?

Говоря о пользователях, есть "tabitha", в чьей директории исполняемый файл находится у пользователя, имеющего проблему? Или мы рассматриваем возможное усложнение попытки запустить программу, установленную другим обычным пользователем, а не обычным общесистемным способом root?

Ответ 4

Из execve manpage:

При успехе execve() не возвращается, возвращается ошибка -1, а errno устанавливается соответствующим образом.

strace предполагает, что -1 означает "файл не найден", поскольку значение errno ENOENT равно -1 и strace не делает различия.

По существу, тогда вы можете игнорировать это: -1 означает только некоторую ошибку. вывод strace не сообщает вам, что такое значение errno.

Я пишу это как предупреждающий вызов, чтобы не переходить к выводам с strace и возвращать значения, хотя может оказаться, что errno есть ENOENT здесь в любом случае.

Ответ 5

Вы можете использовать readelf (любой файл readelf должен делать, вам не нужен один из специальной привязки для кросс-компилятора), чтобы проверить, какой загрузчик ожидается динамически загруженным или исполняемым.

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