[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Getting process id of started process

Joe Van Dyk

3/30/2005 10:58:00 PM

Say I want to start a long running shell process (and monitor that process).


def start_process
@process_id = fork do
Kernel.system "cat /dev/zero > /dev/null"
end
end

However, @process_id doesn't contain the pid of the cat process. How
can I capture the pid of that process?

Thanks,
Joe


6 Answers

Joe Van Dyk

3/31/2005 12:02:00 AM

0

I've attatched code and test code at
http://rafb.net/paste/results/2Rj... , if someone wants to take
a look. Hopefully it's clear about what I want to do.


On Wed, 30 Mar 2005 14:57:51 -0800, Joe Van Dyk <joevandyk@gmail.com> wrote:
> Say I want to start a long running shell process (and monitor that process).
>
> def start_process
> @process_id = fork do
> Kernel.system "cat /dev/zero > /dev/null"
> end
> end
>
> However, @process_id doesn't contain the pid of the cat process. How
> can I capture the pid of that process?
>
> Thanks,
> Joe
>


Ben Giddings

3/31/2005 12:14:00 AM

0

Joe Van Dyk wrote:
> I've attatched code and test code at
> http://rafb.net/paste/results/2Rj... , if someone wants to take
> a look. Hopefully it's clear about what I want to do.
>
>
> On Wed, 30 Mar 2005 14:57:51 -0800, Joe Van Dyk <joevandyk@gmail.com> wrote:
>
>>Say I want to start a long running shell process (and monitor that process).
>>
>> def start_process
>> @process_id = fork do
>> Kernel.system "cat /dev/zero > /dev/null"
>> end
>> end
>>
>>However, @process_id doesn't contain the pid of the cat process. How
>>can I capture the pid of that process?

I think what you need is "$?", which is "The status of the last executed
child process."

You might want to look at the docs here:

http://www.ruby-doc.org/core/classes/Kernel.ht...

It says that in block form, fork returns zero, but it might set $?, I'm
not sure.

In any case, you might need to use the non-block form of fork to do what
you want. That way you'll either get the process ID or nil:

def start_process
@process_id = fork
if @process_id
# We're in the parent
else
system("cat /dev/zero > /dev/null")
Process.exit!(0)
end

@process_id
end

Anyhow, the Process documentation seems to be pretty good:

http://www.ruby-doc.org/core/classes/Pr...

Ben


ES

3/31/2005 12:20:00 AM

0


In data 3/31/2005, "Joe Van Dyk" <joevandyk@gmail.com> ha scritto:
>I've attatched code and test code at
>http://rafb.net/paste/results/2Rj... , if someone wants to take
>a look. Hopefully it's clear about what I want to do.
>
>
>On Wed, 30 Mar 2005 14:57:51 -0800, Joe Van Dyk <joevandyk@gmail.com> wrote:
>> Say I want to start a long running shell process (and monitor that process).
>>
>> def start_process
>> @process_id = fork do
>> Kernel.system "cat /dev/zero > /dev/null"
>> end
>> end
>>
>> However, @process_id doesn't contain the pid of the cat process. How
>> can I capture the pid of that process?

Kernel#fork returns twice, once in the child (return value of
nil), once in the parent (returns the pid). Try a if/else block
and see if it works?

Re: $?, I think that is the only way to get the Process::Status
object. I do not think Process#wait(pid) returns immediately
though I may be wrong.

>> Thanks,
>> Joe

E



Sam Roberts

3/31/2005 1:55:00 PM

0

Wrote Joe Van Dyk <joevandyk@gmail.com>, on Thu, Mar 31, 2005 at 07:58:11AM +0900:
> Say I want to start a long running shell process (and monitor that process).
>
>
> def start_process
> @process_id = fork do
> Kernel.system "cat /dev/zero > /dev/null"
> end
> end
>
> However, @process_id doesn't contain the pid of the cat process. How
> can I capture the pid of that process?

You can't, not like this anyhow. You aren't running cat directly, you
are calling the shell, /bin/sh, which is processing the redirect command
(>/dev/null). Only the shell knows the pid of cat. You actually have

ruby --fork()--> ruby --system()--> /bin/sh --fork()/exec()--> /bin/cat

So there are 3 processes inherited from your main ruby executable.

Kernel.fork/exec/system are fairly thin wrappers around the C
equivalents, so a unix prog manual should cover whats happening, as well
as ways of doing whatever you are trying to do.

Sam

--
Sam Roberts <sroberts@certicom.com>


Brian Candler

3/31/2005 5:27:00 PM

0

On Thu, Mar 31, 2005 at 09:02:02AM +0900, Joe Van Dyk wrote:
> On Wed, 30 Mar 2005 14:57:51 -0800, Joe Van Dyk <joevandyk@gmail.com> wrote:
> > Say I want to start a long running shell process (and monitor that process).
> >
> > def start_process
> > @process_id = fork do
> > Kernel.system "cat /dev/zero > /dev/null"
> > end
> > end
> >
> > However, @process_id doesn't contain the pid of the cat process. How
> > can I capture the pid of that process?

It won't, because Kernel.system also does a fork, runs the 'cat' as a child,
waits for it to finish, and then continues.

You will get the pid of the cat process if you change Kernel.system "cat..."
to
exec "cat ..."

But then, the child Ruby process *becomes* cat at that point, and so when
cat terminates, the child terminates.

If you want to capture the pid of the 'cat' then you can reimplement
Kernel.system yourself - which is basically just fork and exec anyway.

It depends what you want to do with the variable @process_id later. If you
just want the child to run cat and then terminate, then 'exec' is what you
want.

In fact, I can't see what else you would want. Suppose I wrote:

def start_process
@process_id = fork do
Kernel.system "cat /dev/zero > /dev/null"
Kernel.system "cat /dev/null > /dev/null"
Kernel.system "cat /dev/zero > /dev/null"
end
end

which process ID would you want returned in @process_id ? You currently get
the (child) Ruby process, which then runs three grandchildren one after
another. I can't see how else it would usefully work, unless you get the pid
of each of the three grandchildren and communicate it back to the parent
somehow (e.g. over a socket). The pid for each grandchild won't be known
until that particular grandchild is started, of course.

Regards,

Brian.


Csaba Henk

4/2/2005 2:21:00 PM

0

On 2005-03-30, Joe Van Dyk <joevandyk@gmail.com> wrote:
> Say I want to start a long running shell process (and monitor that process).
>
>
> def start_process
> @process_id = fork do
> Kernel.system "cat /dev/zero > /dev/null"
> end
> end
>
> However, @process_id doesn't contain the pid of the cat process. How
> can I capture the pid of that process?

To ensure that the called program really runs as the child of the main
process (and not a further descendent), you have to code it in a
relatively low-level way; in the above case it would look like

def start_process
@process_id = fork do
File.reopen $stdin, File.open("/dev/null","w")
exec %w(cat /dev/zero)
end
end

(In this case, 'exec "cat /dev/zero"' would do as well. Ruby's exec is a
bastardized one, not just an interface to the posix exec* calls: it
tries to find out by itself whether to exec the program directly or to
do it via shell. In general, passing an array to exec protects from
shell expansion.)

I'm working on a lib which makes it easier, eg. you could do with it:

def start_process
po = Pope.new
po.do(%w(cat /dev/zero), 1 => "/dev/null").end
@process_id = po.actors[0].child
end

Csaba