4

I wrote this code to check if any process with the name Rahul is running or not:

  int ret = -1;
  char cmd[40]="pgrep -f Rahul > /dev/null";
  ret = WEXITSTATUS(system(cmd));
  printf("%d\n", ret);

This code prints 0 indicating that a process whose name contains Rahul exists though I had verified no such process was running.

I modified the code and removed the output redirect part, so the modified code is:

  int ret = -1;
  char cmd[40]="pgrep -f Rahul";
  ret = WEXITSTATUS(system(cmd));
  printf("%d\n", ret);

Here, the output is 1, that is, the code works fine.

Can someone suggest why this behaviour?

msw
  • 42,753
  • 9
  • 87
  • 112
  • 1
    Alternatively, you could try to use `pgrep -c` to make `pgrep` not produce output. – fuz Aug 17 '15 at 10:33
  • 1
    @FUZxxl: I think "pgrep -c" produces as outpur the number of matching processes. – pasaba por aqui Aug 21 '15 at 18:23
  • @pasabaporaqui Ah, yes, that's correct. I thought `pgrep` *returned* this number instead of printing it for some reason. Sadly, `pgrep` has no `-q` option like `grep` has. – fuz Aug 21 '15 at 18:46
  • A side note, you should probably put return value of `system` to another variable, and use `WEXITSTATUS` macro on that, ideally only after checking `WIFEXITED`. Would make it much easier to spot cases where the program failed to execute completely, or was terminated by signal, and there's no meaningful exit status. See [this man page](http://linux.die.net/man/2/wait) for more. – hyde Sep 01 '15 at 11:20

1 Answers1

3

You are facing an special behavior of "bash" combined with the ones of "pgrep".

First, we can simplify the issue using simple commands:

$ bash -c "pgrep -l -f Rahul"; echo $?
1
$ bash -c "pgrep -l -f Rahul > /dev/null"; echo $?
0

Now, we can see the internals of each one:

$ strace -tt -F bash -c "pgrep -l -f Rahul" 2>&1 | egrep "exec|clone|dup|write"
19:47:50.336043 execve("/bin/bash", ["bash", "-c", "pgrep -l -f Rahul"], [/* 55 vars */]) = 0
19:47:50.343015 execve("/usr/bin/pgrep", ["pgrep", "-l", "-f", "Rahul"], [/* 54 vars */]) = 0
19:47:50.353342 read(4, "Name:\twriteback\nState:\tS (sleepi"..., 1024) = 538
19:47:50.387157 read(4, "egrep\0exec|clone|dup|write\0", 2047) = 27
19:47:50.387668 write(1, "3031 strace\n", 123031 strace

compared with:

$ strace -tt -F bash -c "pgrep -l -f Rahul > /dev/null" 2>&1 | egrep "exec|clone|dup|write"
19:48:44.669747 execve("/bin/bash", ["bash", "-c", "pgrep -l -f Rahul > /dev/null"], [/* 55 vars */]) = 0
19:48:44.676633 clone(Process 3046 attached
[pid  3046] 19:48:44.677336 dup2(3, 1)  = 1
[pid  3046] 19:48:44.677435 execve("/usr/bin/pgrep", ["pgrep", "-l", "-f", "Rahul"], [/* 54 vars */]) = 0
[pid  3046] 19:48:44.687636 read(4, "Name:\twriteback\nState:\tS (sleepi"..., 1024) = 538
[pid  3046] 19:48:44.727507 read(4, "egrep\0exec|clone|dup|write\0", 2047) = 27
[pid  3046] 19:48:44.728375 write(1, "3039 strace\n3045 bash\n", 22) = 22

see that only in second one a "clone" is done. "pgrep" then is finding the shell as a matching process.

pasaba por aqui
  • 3,446
  • 16
  • 40