Команды, выполняемые 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";
}