Способ, которым функция system
обычно работает на * nix, заключается в том, что она вызывает fork
, а затем дочерний элемент вызывает одну из exec
функций с /bin/sh
-c
, а затем строку, которую вы передали system
в дочернем элементе, который превращает дочерний процесс в экземпляр программы /bin/sh
, которая выполняет команду.Родитель вызывает одну из функций wait
, которая ожидает выхода /bin/sh
, что происходит с тем же состоянием выхода, что и сценарий оболочки, а затем system
также возвращает это значение.
Если вы посмотрите справочные страницы по системным вызовам wait
:
main 3 wait
Вы должны получить некоторую информацию о том, что получает возврат, и некоторые макро-функции, которые помогут вам разобраться в этом.
Макрос WIFEXITED(stat_val)
можно использовать для проверки, нормально ли завершился процесс, в отличие от сигнала.Обычные выходы включают вызов системного вызова exit
.Если эта функция возвращает ненулевое значение, вы можете использовать макрос WEXITSTATUS(stat_val)
, чтобы получить значение, которое она фактически вернула.
Макрос WIFSIGNALED(stat_val)
можно использовать для проверки, была ли программа завершена ссигнал, и если это так, макрос WTERMSIG(stat_val)
вернет номер сигнала, который вызвал завершение.
Есть некоторые другие макросы, которые могут сообщить вам, если процесс был остановлен или продолжен, а не завершен, но я неНе думаю, что они слишком полезны для этой цели, но вы, возможно, захотите разобраться с ними.
Что касается того, что на самом деле происходит в этом случае, может быть трудно сказать.Если вызов fork
завершится неудачно, system
сможет вернуть -1 и установить errno
для отражения ошибки.Если fork
не дал сбоя, возможно, ошибка произошла у ребенка, и ее будет труднее найти.Вполне возможно, что на вашей платформе system
может выполнить некоторые тесты перед разветвлением, чтобы убедиться, что у вас есть разрешение на выполнение соответствующих файлов и установите errno
для отражения этого, но, возможно, нет.
Вы должны посмотретьв функцию perror
для вывода сообщений об ошибках в случае, если установлено значение errno
.
Если сбой происходит после fork
и внутри дочернего элемента, то вам нужно либо получить оболочку, чтобы сообщить вамбольше о том, что происходит, или получите скрипт оболочки.Это может быть связано с включением в скрипт echo
операторов, аналогично использованию операторов print в ваших программах на C.
Вам также следует изучить функцию access
, чтобы проверить, есть ли у вас разрешение на чтение и / или выполнение.файлы.
Если вы используете Linux, то вы должны сделать:
strace -o my_program.strace -f ./my_program
или
ltrace -o my_program.ltrace -f -S ./my_program
, а затем изучить файлы трассировки (после -o
) чтобы посмотреть, что программы и ядро говорят друг другу.ltrace
смотрит на то, как программа общается с библиотечной функцией, а strace смотрит на системные вызовы, но -S
говорит, что ltrace также смотрит на системные вызовы.Аргумент -f
говорит им обоим отслеживать детей программы по мере их создания.
Я только что заметил, что вы сказали, что используете ksh
Как я уже упоминал system
подСистема Posix должна использовать /bin/sh
или совместимую оболочку.Это не означает, что /bin/sh
не будет запускать /bin/ksh
для запуска вашего скрипта (или что ядро не будет использовать строку #!
в начале файла скрипта для этого), но это может бытьпроблема.Существуют способы запуска сценариев оболочки, так что эта строка не используется, чтобы узнать, какую оболочку следует использовать.Наиболее примечательным является:
. myshell.sh
Период и пробел, по сути, пытаются записать текст файла в текущий сеанс оболочки, а не запускать его в другом процессе (это полезно для настройки среды).Если бы вы делали:
int x = system(". myshell.sh");
Тогда это может быть проблемой.