Будет ли std :: system выполняться даже после выхода из родительского процесса? - PullRequest
0 голосов
/ 12 февраля 2019

Я запускаю консольное приложение C ++ во встроенной среде linux .Я хочу выполнить команду std::system, как это.Я взял tar в качестве примера.

int main(int argc, char *argv[]) {
    std::system("tar xvzf /path/to/some/file.tar.gz");
    exit 0;
}

Вопрос:
Если я выйду из приложения сразу после команды tar, как описано выше, будет ли команда tar продолженавыполнить?
Я понимаю, что это немного зависит от того, как tar реализован сам.Но допустим, что tar не работает после выхода из родительского процесса ( с учетом наихудшего сценария ), есть ли способ, которым я могу безопасно выполнить команду std::system command в фоновом режиме и выйти из моего приложения, полагая, что онозавершит свою работу после завершения работы моего приложения или родительского процесса?

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

std::system - это блокирующий вызов ... Это означает, что вы не достигнете выхода до завершения самой команды tar.

0 голосов
/ 12 февраля 2019

Команды, выполняемые system(), обычно не продолжаются после возврата system().system() запускает новый процесс (используя fork() + exec*() или CreateProcess() и т. Д.), А затем ожидает завершения этого процесса, прежде чем он вернется.Однако если команда порождает осиротевших детей, то они могут жить.

Это может иметь такой эффект в зависимости от SHELL, используемого system():

std::system("nohup tar xvzf /path/to/some/file.tar.gz &");

С system()запускает команду, используя оболочку (вероятно, /bin/sh) и что она, в свою очередь, использует текущую среду процесса (прежде всего PATH и переменные, которые могут использоваться, чтобы повлиять на то, какие общие библиотеки используются командой) - и что вытакже может отправлять строки команд с перенаправлениями, помещать команды в фоновом режиме (как показано выше) и т. д. - это часто считается угрозой безопасности.Один из способов минимизировать риск - создать собственную системную функцию, которая не использует оболочку или среду.Пример:

#include <iostream>
#include <array>
#include <type_traits> // std::common_type_t
#include <cstdlib>     // std::exit
#include <utility>     // std::forward

// fork, exec, waitpid
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

template<typename... Ts>
int mysystem(Ts&&... ts) {
    int wstatus=-1;

    pid_t pid = fork();

    if(pid==0) {          // in child process
        std::array<std::common_type_t<Ts...>, sizeof...(ts) + 1> cmd{ std::forward<Ts>(ts)... };
        execv(cmd[0], const_cast<char* const*>( cmd.data() ));
        std::exit(1); // we'll only get here if execv failed starting the command

    } else if(pid!=-1) { // in parent process
        // wait for the child to terminate
        // the exit status from the child will be returned in wstatus
        waitpid(pid, &wstatus, 0); // 0 = wait forever

    } // else { /* fork() failed */ }

    return wstatus;
}

int main() {
    //int ws = mysystem("/usr/bin/find", ".");
    //int ws = mysystem("/usr/bin/bash", "-i");
    int ws = mysystem("/usr/bin/tar", "xvzf", "/path/to/some/file.tar.gz");
    std::cout << "--------------------\n"
                 "Exit status:        " << WEXITSTATUS(ws) << "\n"
                 "Termination signal: " << WTERMSIG(ws) << "\n"
                 "Core dumped:        " << std::boolalpha << WCOREDUMP(ws) << "\n";
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...