На пару RHEL 5.8 я столкнулся с проблемой с execve звонками. Однако execve не завершается с ошибкой, получая следующую ошибку:
/bin/bash: h: No such file or directory
Я использую его следующим образом в коде C ++:
::fork();
.
.
.
char achWritePipeDescriptor[8], achReadPipeDescriptor[8];
snprintf(achWritePipeDescriptor, sizeof(achWritePipeDescriptor), "%d", fWritePipeDescriptor);
snprintf(achReadPipeDescriptor, sizeof(achReadPipeDescriptor), "%d", fReadPipeDescriptor);
// fWritePipeDescriptor and fReadPipeDescriptor are integers
::execl("/bin/sh", "/bin/sh", "Launcher.sh", achWritePipeDescriptor, achReadPipeDescriptor, (char*)0);
switch(errno)
{
default:
printf("\n Failed to launch Launcher.sh\n");
break;
}
Вызов exec здесь не сбой, но я получаю выше ошибку при попытке взаимодействия с вышеупомянутым script.sh. Вывод strace для этого процесса выглядит следующим образом:
execve("/bin/bash", ["/bin/bash", "h", "10", "6"], [/* 36 vars */]) = 0
.
.
.
open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
fstat(2, 0x7fff23708910) = -1 EBADF (Bad file descriptor)
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b9d1c785000
write(2, "/bin/bash: h: No such file or di"..., 40) = -1 EBADF (Bad file descriptor)
exit_group(127) = ?
Process 13030 detached
Здесь нет ссылки на файл «h», но последний символ имени скрипта — «h». Кроме того, скрипт, который я пытаюсь выполнить, существует в ожидаемом месте и имеет достаточные разрешения.
Я понятия не имею, откуда идет «ч».
Я изменил свой execve вызов на следующее:
::execl("Launcher.sh", "Launcher.sh", achWritePipeDescriptor, achReadPipeDescriptor,(char*)0);
При этом все работало правильно, но, следуя приведенному ниже коду, я вижу похожую ошибку для другого вызова execl. Разница во втором exec заключается в том, что двоичный файл отличается, но ошибка остается той же.
Я не уверен, если это проблема конкретного сервера.
Любые подсказки, любые шаги по устранению неполадок будут очень полезны.
Мой Плохой, я должен был упомянуть об этом раньше, <script.sh>
это заполнитель. Я пытался указать, что сценарий оболочки — это то, что я пытаюсь выполнить.
Также, writefd
а также readfd
являются char*
Вот. Это хорошо видно по выводу strace, который я здесь вставил. Опять же, здесь не происходит сбой exec, поскольку я не вижу сообщения «Не удалось запустить Launcher.sh».
Есть еще одна проблема здесь в дополнение к <script.sh>
против "script.sh"
проблема, решаемая MikeyB. Эта другая проблема writefd
а также readfd
передается execl
, Учитывая имена, я предполагаю, что это конец записи одного канала и конец чтения другого канала. Если это так, writefd
а также readfd
целые числа, а не char*
указатели.
Самый простой способ заставить некоторый скрипт связываться с вашей программой через каналы — это dup2
конец чтения одного конвейера для стандартного ввода и dup2
конец записи другого конвейера в стандартный вывод перед вызовом execl
, Скрипт просто читает из стандартного ввода и записывает в стандартный вывод. Вам вообще не нужно передавать эти файловые дескрипторы в скрипт.
execl("/bin/sh", "/bin/sh", <script.sh>, writefd, readfd, NULL);
Это просто не будет работать … <script.sh>
не действителен C ++.
Измените это на:
execl("/bin/sh", "/bin/sh", "script.sh", writefd, readfd, NULL);