我正在嵌入式Linux 环境中运行 C ++ 控制台应用程序。我想像这样运行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
并退出我的应用程序是否相信它将在我的应用程序或父进程退出后完成工作?
答案 0 :(得分:4)
system()
返回后通常不会继续执行system()
执行的命令。 system()
启动一个新进程(使用fork() + exec*()
或CreateProcess()
等),然后等待直到该进程完成后再返回。但是,如果该命令生成了孤儿,则他们可能会继续生活。
这取决于SHELL
使用的system()
:
std::system("nohup tar xvzf /path/to/some/file.tar.gz &");
由于system()
使用外壳程序启动了命令(可能是/bin/sh
),并且依次使用了进程的当前环境(最著名的是PATH
和可能用来影响哪个变量的变量)该命令使用的共享库)-您还可以通过重定向发送命令字符串,将命令置于后台(如上所示)等-通常被认为存在安全风险。最小化风险的一种方法是创建自己的不使用Shell或环境的系统功能。示例:
#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";
}
答案 1 :(得分:3)
std::system
是一个阻止呼叫...
这意味着您不会在tar命令本身完成之前到达出口。