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]