C-программа вызывает скрипт оболочки - PullRequest
3 голосов
/ 15 ноября 2010

У меня есть небольшая программа на C, вызывающая сценарий оболочки myScript.sh.Я получаю значение ret как 256. Пожалуйста, помогите мне узнать, что пошло не так с системным вызовом?

int main()
{
int ret;
ret = system (myScript.sh);
ret >>=  ret;
if (ret != 0)
{
  printf("ret is [%d]",ret);
}
}

Работа в 64-битной операционной системе UNIX и использование оболочки ksh

Ответы [ 8 ]

5 голосов
/ 15 ноября 2010

В моей системе man system говорит:

 The system() function returns the exit status of the shell as returned by
 waitpid(2), or -1 if an error occurred when invoking fork(2) or
 waitpid(2).  A return value of 127 means the execution of the shell
 failed.

Страница man waitpid описывает набор макросов, таких как WEXITSTATUS(), которые извлекают фактический код выхода извозвращаемое значение.

Я не совсем уверен, что вы собираетесь делать с ret >>= ret, но это не может быть правильным.

4 голосов
/ 15 ноября 2010

Способ, которым функция 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");

Тогда это может быть проблемой.

2 голосов
/ 15 ноября 2010

из стандарта (выделено моё):

6.5.7 / 3 Если значение правого операнда [оператора >>] отрицательно или больше или равноширина повышенного левого операнда, поведение не определено .

Итак, когда вы делаете

ret >>= ret;

и ret < 0 или ret >= CHAR_BIT * sizeof (int)... все идет


Возвращаемое значение функции system может быть -1 при ошибке.

Если ваш вызов вернул такое отрицательное значение, следующая операция ret >>= ret; (так же, как ret = -1 >> -1;) приводит к чему-то, что не имеет смысла: вы не можете сдвинуть вправо на отрицательное число битов.

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

2 голосов
/ 15 ноября 2010

Статус выхода команды кодируется в виде двух байтов:

  • Старший байт содержит состояние выхода.
  • Байт младшего порядка содержит сигнал, который убилэто (если есть).

Поскольку 0x0100 является 256 десятичным знаком, ваш сценарий оболочки завершился со статусом 1. Просмотрите сценарий оболочки и убедитесь, что он завершается со статусом 0, если он успешен.

1 голос
/ 15 ноября 2010

Убедитесь, что ваш скрипт исполняемый и находится в пути, или используйте вместо него полный путь.

0 голосов
/ 10 октября 2015

Я работаю на Linux, и это помогло вызвать скрипт с системой ("sh script.sh")

0 голосов
/ 15 ноября 2010

Почему вы меняете результат?Просто удалите строку ret >> = ret, и она будет работать.

0 голосов
/ 15 ноября 2010

Ничего не пошло не так. Вы читали документацию? См:

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Возвращаемое значение равно -1 при ошибке (например, не удалось выполнить fork (2)), а в противном случае верните статус команды. Последний статус возврата имеет формат, указанный в wait (2). Таким образом, код выхода команды будет WEXITSTATUS (статус). В случае, если / bin / sh не может быть выполнен, статус выхода будет соответствовать команде, которая завершает работу (127).

Поскольку 256 не равно -1, вызов не состоялся.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...