2

I am trying to execute (fork off) a command with popen and what I see is, there is an extra sh -c "my_command process" is also there.

I want to minimize number of processes so is it possible to get rid of it?

ps output:

root@home% ps awux | grep my_command
root 638  0.0  0.1  040  1424  ??  I    10:12PM   0:00.00 sh -c my_command /home/war
root 639  0.0  0.0  608   932  ??  S    10:12PM   0:00.01 my_command /home/war

After reading manpage, I know this is how popen() works.

Answer to problem above was provided by @R..

My requirement is as such, I need to dump output of the command into a file and read that file line by line and process the output. This is why I am using popen because, it returns output in a file. Can I achieve that via any exec call?

hari
  • 9,439
  • 27
  • 76
  • 110
  • Show us the relevant part of your code. – NPE Jul 19 '11 at 05:28
  • If this is how popen() is supposed to work, so what is the other alternative for me? – hari Jul 19 '11 at 05:28
  • 1
    @aix: why? I believe this question is self sufficient. Isn't it? – hari Jul 19 '11 at 05:30
  • @hari: If - almost 7 years later - you're still interested as to _why_ the additional `sh` process is being used (as you indicated in the comments below), I've asked a [specific question](https://stackoverflow.com/questions/48884454/why-does-popen-invoke-a-shell-to-execute-a-process) on that. – domsson Feb 20 '18 at 12:20

3 Answers3

3

You should listen to the good folks who are advising you not to use popen - it's bad. But there is a simple fix for the issue you've encountered - add exec to the beginning of the command line you pass to popen. That is, instead of:

popen("my_command /home/war", ...

use:

popen("exec my_command /home/war", ...
R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 1
    Thanks. I surely listens to everyone. I am just trying to understand why it is bad. If its bad, why is it designed/implemented/standardize/used this way. Again, for my education :) Thanks a bunch. – hari Jul 19 '11 at 06:11
  • 1
    It's bad because.. (1) invoking external programs via a shell introduces shell meta-char vulns if you're not careful to quote, (2) `popen` only allows one-way communication, not two-way, and (3) you have no access to the pid of the child process, so it makes problems if you want to `wait` for other child processes you created. Probably other issues too... – R.. GitHub STOP HELPING ICE Jul 19 '11 at 06:15
  • Agree to (1) and (3). How is popen a one-way communication? thanks. – hari Jul 19 '11 at 06:19
  • 2
    @hari Most implementations allow only `popen("...", "r")` or `popen("...", "w")`. That is you can only write **or** read. As an exception, BSD allows "r+". – cnicutar Jul 19 '11 at 06:28
2

popen uses sh to spawn the child process, like system does on POSIX systems.

If you want to avoid it, just use fork, close, mkpipe and exec (which is more or less what popen does internally). If you don't need the pipe you can just fork and exec.

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • 1
    Thanks for the response. For my education, why does popen does it? if its avoidable. Why to create an extra process? – hari Jul 19 '11 at 05:35
  • Using a shell as an intermediate step allows the code to use shell builtins/facilities. I don't see other advantages than this. Still, as explained, you can easily avoid it using syscalls. – Matteo Italia Jul 19 '11 at 05:41
  • Let's suppose the command were a shell script. Even if the execute bit were set, you still need to pass this through sh or bash (running exec on a shell script fails). Hence, since there is no requirement that any program be implemented as a c program, it's possible that you may want to use a shell script, and it's easier to just pass through the shell. (those other scripts, like python and perl, are resolved by the shell when it parses the shebang line, hence other scripts are also supported) – Foo Bah Jul 19 '11 at 05:52
  • 1
    @Foo Bah: actually IIRC the shebang notation is handled directly by `exec`, no shell is necessary for it. Also (again, IIRC) when you start a shell script from a shell the shell the process is not reused, but another one is started (unless you use the `. ` command). – Matteo Italia Jul 19 '11 at 06:02
  • I'm late to the party, but I tend to agree with @MatteoItalia: at least the [manpage for `execve`](https://linux.die.net/man/2/execve) explicitly states: _"execve() executes the program pointed to by filename. filename must be either a binary executable, or a script starting with a line of the form: `#! interpreter [optional-arg]`"_ - which should also hold true for `execvp`, as its manpage referes to that of `execve` - not sure about the other functions of the family. – domsson Feb 20 '18 at 11:57
1

As far as popen is concerned, it is supposed to invoke the shell (read the manpage)

To skip the shell process, you can do a fork/exec

Foo Bah
  • 25,660
  • 5
  • 55
  • 79