0

Since the function std::system(const char* command) from cstdlib doesn't guarantee that will return the correct return status from the shell, then how can I run a command in shell using c/c++ and have a guarantee that will give me the right return value?

In my case, for example, I ran a command with:

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;
}

If I run, for example, ps aux | grep 'my_process' | egrep -v '(grep|bash)' directly into the terminal and after that echo $?, I see it returning 0 because my_process is running and also returning 1 when I use a non running process. But, the code above returns a different value. This code used to work when I tested in CentOs 6 but now in CentOs 7 doesn't work anymore. So, what can I use to run the shell command and get the correct result?

I also found a solution using pidof command but I can't use this because pidof doesn't consider the parameters passed to my_process which I need since I have many instances of this process each with different arguments.

Fnr
  • 2,096
  • 7
  • 41
  • 76
  • What shell are you using? If you want guarancy, run `popen` 3 times for each process `ps`, `grep` and `egrep` with pipes between them. – KamilCuk Sep 05 '18 at 11:51
  • It's better to use `pgrep my_process` to check if a process named my_process is running. Using `ps | grep` pipe will may give you false positives. – KamilCuk Sep 05 '18 at 11:53
  • Possible duplicate of [How to execute a command and get return code stdout and stderr of command in C++](https://stackoverflow.com/questions/52164723/how-to-execute-a-command-and-get-return-code-stdout-and-stderr-of-command-in-c) – 463035818_is_not_an_ai Sep 05 '18 at 11:53
  • If you want to understand how something works, you need to cut through the layers of abstraction. You can implement this using `fork`, `pipe`, and `exec`. – William Pursell Sep 05 '18 at 11:57
  • Oof, that function gives me tingles. Be _very very careful_ about what you allow to pass into `is_process_running`. You'd be better off taking some non-shell approach: does your OS not provide an API for this kind of thing? – Lightness Races in Orbit Sep 05 '18 at 12:32

1 Answers1

0

The problem is that the exit status of Bash isn't guaranteed to be the exit status of the last executed command. If there's an error in the command you pass, you can't really distinguish it from egrep failing to match anything.

What you need to do is to do is to both get the exit status and parse the output (both to standard output and standard error). This can be accomplished by copying much of what the system function does: First create a pipe for the output (both stderr and stdout could be using the same pipe), then fork a new process to run the shell, and then execute the shell and the pipeline.

In the parent process you wait for the child to exit, and get its exit status. If it's zero then you know everything worked fine, and you can discard all the output from the pipe. If it's non-zero you have to read the output from the pipe to see what happened, if there was some error except egrep failing.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 2
    @Fabiotk There are several thousands of examples on how to use these functions, all over the Internet (and quite a few of them here on this site). Please do some searching first. – Some programmer dude Sep 05 '18 at 12:18