Запуск команды оболочки в программе на c

#c #linux #shell

#c #linux #оболочка

Вопрос:

Я хочу запустить команду оболочки в моей программе на C. Но дело в том, что я не хочу заставлять свою программу ждать, пока команда не будет выполнена. Нет необходимости читать выходные данные команды оболочки (она все равно не возвращает никаких данных) Итак, в принципе, возможно ли это?

Комментарии:

1. Кстати, не имеет значения, хотите ли вы запустить команду оболочки или какой-либо другой исполняемый файл. Используете ли вы system() или fork()/exec() подход, все, что требуется, — это исполняемый файл. Может быть, вы хотите соответствующим образом отредактировать заголовок вашего вопроса?

Ответ №1:

Конечно, просто fork и exec : используйте fork для создания нового процесса, а в дочернем процессе используйте exec для запуска командной строки с вашей командой. execv принимает аргументы, которые вы обычно передаете командной строке.

Ваш код может выглядеть следующим образом:

 pid_t child_pid = fork();
if (child_pid == 0)
{   // in child
    /* set up arguments */
    // launch here
    execv("/bin/sh", args);
    // if you ever get here, there's been an error - handle it
}
else if (child_pid < 0)
{   // handle error
}
  

дочерний процесс отправит SIGCHLD сигнал, когда он завершит работу. Этот код, приведенный из стандарта POSIX (SUSv4), справится с этим:

 static void
handle_sigchld(int signum, siginfo_t *sinfo, void *unused)
{
    int status;

    /*
     * Obtain status information for the child which
     * caused the SIGCHLD signal and write its exit code
     * to stdout.
    */
    if (sinfo->si_code != CLD_EXITED)
    {
        static char msg[] = "wrong si_coden";
        write(2, msg, sizeof msg - 1);
    }
    else if (waitpid(sinfo->si_pid, amp;status, 0) == -1)
    {
        static char msg[] = "waitpid() failedn";
        write(2, msg, sizeof msg - 1);
    }
    else if (!WIFEXITED(status))
    {
        static char msg[] = "WIFEXITED was falsen";
        write(2, msg, sizeof msg - 1);
    }
    else
    {
        int code = WEXITSTATUS(status);
        char buf[2];
        buf[0] = '0'   code;
        buf[1] = 'n';
        write(1, buf, 2);
    }
}
  

Комментарии:

1. exec не использует оболочку. предположим, что операционная система хочет выполнить ls | grep -v hello . Это будет работать с system, но не будет работать с exec.

2. операционная система может передавать их в оболочку — система делает то же самое (но делает другое fork amp; exec за кулисами).

Ответ №2:

fork() и system() это то, что вам нужно

Комментарии:

1. Возможно, вместе с exec() или его вариантами.

2. system заставил бы дочерний процесс ожидать команды оболочки — exec заменил бы дочерний процесс оболочкой..

3. @Ronald: нет. Дочерний процесс заменяется другим процессом. Из OP неясно, хочет ли он запустить другую программу или командную строку оболочки, но если это последнее, то только system () справится с задачей. exec не использует оболочку.

4. это произойдет, если вы передадите ей надлежащие аргументы (т. Е. запустите /bin/sh и передадите ему скрипт, который вы хотите запустить).

Ответ №3:

Попробуйте код, подобный этому:

 #include <stdlib.h>
#include <unistd.h>
int main(int argc, char ** argv)
{
     if (!fork())
     {
         execv("ls", {"myDir"}); /* Your command with arguments instead of ls. */
     }
}
  

Комментарии:

1. Это кажется мне слишком быстрым и грязным, поскольку это создало бы процесс-зомби с момента завершения работы команды до завершения работы main. Хорошо управляемая программа Unix хотела бы избежать этого. Смотрите другие ответы, которые используют waitpid .

Ответ №4:

Как насчет простого усиления команды с помощью system ("command amp;") ?