Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using exec to execute a system command in a new process

I am trying to spawn a process that executes a system command, while my own program still proceeds and two processes will run in parallel. I am working on linux.

I looked up online and sounds like I should use exec() family. But it doesn't work quite as what I expected. For example, in the following code, I only see "before" being printed, ,but not "done".

I am curious if I am issing anything?

#include <unistd.h>
#include <iostream>

using namespace std;

main()
{
   cout << "before" << endl;
   execl("/bin/ls", "/bin/ls", "-r", "-t", "-l", (char *) 0);
   cout << "done" << endl;
}

[UPDATE]

Thank you for your guys comments. Now my program looks like this. Everything works fine except at the end, I have to press enter to finish the program. I am not sure why I have to press the last enter?

#include <unistd.h>
#include <iostream>

using namespace std;

main()
{
   cout << "before" << endl;
   int pid = fork();
   cout << pid << endl;
   if (pid==0) {
      execl("/bin/ls", "ls", "-r", "-t", "-l", (char *) 0);
   }
   cout << "done" << endl;
}
like image 843
CuriousMind Avatar asked Apr 12 '11 06:04

CuriousMind


People also ask

What will happen to my current process when I execute a command using exec?

Whenever we run any command in a Bash shell, a subshell is created by default, and a new child process is spawned (forked) to execute the command. When using exec, however, the command following exec replaces the current shell. This means no subshell is created and the current process is replaced with this new command.

What is the use of exec () system call?

The exec system call is used to execute a file which is residing in an active process. When exec is called the previous executable file is replaced and new file is executed.

How does exec work in Linux?

The Linux exec command executes a Shell command without creating a new process. Instead, it replaces the currently open Shell operation. Depending on the command usage, exec has different behaviors and use cases.

What are the parameters of the exec () system call?

In execl() system function takes the path of the executable binary file (i.e. /bin/ls) as the first and second argument. Then, the arguments (i.e. -lh, /home) that you want to pass to the executable followed by NULL. Then execl() system function runs the command and prints the output.


2 Answers

You're missing a call to fork. All exec does is replace the current process image with that of the new program. Use fork to spawn a copy of your current process. Its return value will tell you whether it's the child or the original parent that's running. If it's the child, call exec.


Once you've made that change, it only appears that you need to press Enter for the programs to finish. What's actually happening is this: The parent process forks and executes the child process. Both processes run, and both processes print to stdout at the same time. Their output is garbled. The parent process has less to do than the child, so it terminates first. When it terminates, your shell, which was waiting for it, wakes and prints the usual prompt. Meanwhile, the child process is still running. It prints more file entries. Finally, it terminates. The shell isn't paying attention to the child process (its grandchild), so the shell has no reason to re-print the prompt. Look more carefully at the output you get, and you should be able to find your usual command prompt buried in the ls output above.

The cursor appears to be waiting for you to press a key. When you do, the shell prints a prompt, and all looks normal. But as far as the shell was concerned, all was already normal. You could have typed another command before. It would have looked a little strange, but the shell would have executed it normally because it only receives input from the keyboard, not from the child process printing additional characters to the screen.

If you use a program like top in a separate console window, you can watch and confirm that both programs have already finished running before you have to press Enter.

like image 197
Rob Kennedy Avatar answered Sep 18 '22 15:09

Rob Kennedy


The Exec family of functions replaces the current process with the new executable.

To do what you need, use one of the fork() functions and have the child process exec the new image.

[response to update]

It is doing exactly what you told it: You don't have to press "enter" to finish the program: It has already exited. The shell has already given a prompt:

[wally@zenetfedora ~]$ ./z
before
22397
done
[wally@zenetfedora ~]$ 0               << here is the prompt (as well as the pid)
total 5102364
drwxr-xr-x.  2 wally wally       4096 2011-01-31 16:22 Templates
...

The output from ls takes awhile so it buries the prompt. If you want output to appear in a more logical order, add sleep(1) (or maybe longer) before the "done".

like image 32
wallyk Avatar answered Sep 21 '22 15:09

wallyk