在 c++ 中从执行的 shell 命令获取返回状态的安全方法是什么?

What is the safe way of get the return status from an executed shell command in c++

本文关键字:状态 返回 安全 方法 是什么 获取 命令 c++ 执行 shell      更新时间:2023-10-16

既然从cstdlibstd::system(const char* command)的函数不能保证会从 shell 返回正确的返回状态,那么我如何使用 c/c++ 在 shell 中运行命令并保证给我正确的返回值?

例如,就我而言,我运行了一个命令:

bool is_process_running(std::string p_name){
std::string command_str= "ps aux | grep '" + p_name + "' | egrep -v '(grep|bash)'";
int result(0);
result= system(command_str.c_str());
return result == 0;
}

例如,如果我运行ps aux | grep 'my_process' | egrep -v '(grep|bash)'直接进入终端,然后echo $?,我看到它返回0,因为my_process正在运行,并且在我使用非正在运行的进程时也返回1。但是,上面的代码返回一个不同的值。当我在 CentOs 6 中测试时,这段代码曾经有效,但现在在 CentOs 7 中不再有效了。那么,我可以使用什么来运行 shell 命令并获得正确的结果?

我还使用pidof命令找到了解决方案,但我不能使用它,因为 pidof 不考虑传递给我需要的my_process参数,因为我有很多这个过程的实例,每个实例都有不同的参数。

问题是 Bash 的退出状态不能保证是上次执行的命令的退出状态。如果您传递的命令中存在错误,则无法将其与egrep不匹配任何内容区分开来。

您需要做的是获取退出状态解析输出(标准输出和标准错误(。这可以通过复制system函数的大部分功能来实现:首先为输出创建一个管道(stderrstdout可能使用相同的管道(,然后分叉一个新进程来运行 shell,然后执行 shell 和管道。

在父进程中,您等待子进程退出,并获取其退出状态。如果它为零,那么您就知道一切正常,您可以丢弃管道的所有输出。如果它不为零,则必须读取管道的输出以查看发生了什么,除了egrep失败之外是否存在一些错误。