首页 > 解决方案 > 从c ++中执行的shell命令获取返回状态的安全方法是什么

问题描述

由于函数std::system(const char* command)fromcstdlib 不保证会从 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我需要的参数,因为我有很多这个进程的实例,每个实例都有不同的参数。

标签: c++centos7c++17

解决方案


问题是Bash 的退出状态不能保证是最后执行命令的退出状态。如果您传递的命令中有错误,您无法真正将其与egrep未能匹配任何内容区分开来。

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

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


推荐阅读