Difference between system() versus exec Kernel methods

I’m trying to understand the difference between the Kernel.system and
Kernel.exec methods. It was explained in an earlier post that .system
started a new process while keeping the old one running, while .exec
replaced the current process with the new one (if I read it correctly).

I created a simple program called test.rb as follows

put “hello”
gets
puts “bye”

and then called it from another program that was simply

system(“ruby test.rb”)

or

exec “ruby test.rb”

I then looked at the processes in Task Manager while running the second
program which calls the first. I expected that with system(“ruby
test.rb”) I would see two ruby processes being run, which indeed
occured.

When I ran the second version with exec “ruby test.rb” there were still
two active Ruby processes being run (I expected only one, since one
process would be replaced by the other).

So, what am I missing? What is the difference between .system and
.exec?

–Alex

On Sun, Feb 21, 2010 at 5:23 PM, Alex DeCaria
[email protected] wrote:

test.rb") I would see two ruby processes being run, which indeed
occured.

When I ran the second version with exec “ruby test.rb” there were still
two active Ruby processes being run (I expected only one, since one
process would be replaced by the other).

So, what am I missing? Â What is the difference between .system and
.exec?

ri Kernel#exec

------------------------------------------------------------ Kernel#exec
exec(command [, arg, …])

 Replaces the current process by running the given external
 _command_. If +exec+ is given a single argument, that argument is
 taken as a line that is subject to shell expansion before being
 executed. If multiple arguments are given, the second and
 subsequent arguments are passed as parameters to _command_ with no
 shell expansion. If the first argument is a two-element array, the
 first element is the command to be executed, and the second
 argument is used as the +argv[0]+ value, which may show up in
 process listings. In MSDOS environments, the command is executed in
 a subshell; otherwise, one of the +exec(2)+ system calls is used,
 so the running command may inherit some of the environment of the
 original program (including open file descriptors).

    exec "echo *"       # echoes list of files in current directory
    # never get here

    exec "echo", "*"    # echoes an asterisk
    # never get here

ri Kernel#system

---------------------------------------------------------- Kernel#system
system(cmd [, arg, …]) => true or false

 Executes _cmd_ in a subshell, returning +true+ if the command was
 found and ran successfully, +false+ otherwise. An error status is
 available in +$?+. The arguments are processed in the same way as
 for +Kernel::exec+.

    system("echo *")
    system("echo", "*")

 _produces:_

    config.h main.rb
    *

I can’t explain it any better than the docs.

Best regards,
Michael G.

That’s well and good. I’ve already read the documentation. But, based
on the documentation I would expect to see only a single process running
after calling the exec method. So, why are there two?

I’m obviously not reading the documentation correctly, and that’s why I
need someone who can explain it.

–Alex

On 2/21/2010 4:38 PM, Alex DeCaria wrote:

That’s well and good. I’ve already read the documentation. But, based
on the documentation I would expect to see only a single process running
after calling the exec method. So, why are there two?

I’m obviously not reading the documentation correctly, and that’s why I
need someone who can explain it.

–Alex

This line from the docs explains it:

  In MSDOS environments, the command is executed in
  a subshell; otherwise, one of the +exec(2)+ system calls is used,
  so the running command may inherit some of the environment of the
  original program (including open file descriptors).

The trick is, exec uses the underlying OSes exec. In Linux, that does
as you
expect and simply replaces the running process in memory. In Windows
however,
there is no equivalent to the Linux exec, so we pretend. Ruby execs the
specified command (via the Windows version of exec which starts a second
process)
and exits once it’s done, thus there are two processes.

To demonstrate this try running the following:

exec “echo boo”
puts “I hope I don’t get here”

Notice that the puts statement never gets run.

Thanks! That makes it clearer. --Alex

On Sun, Feb 21, 2010 at 5:58 PM, Walton H. [email protected]
wrote:

expect and simply replaces the running process in memory. In Windows
however,
there is no equivalent to the Linux exec, so we pretend. Ruby execs the
specified command (via the Windows version of exec which starts a second
process)
and exits once it’s done, thus there are two processes.

Sounds like the doc should be updated to mention Windows.