Getting process id of started process

Discussion in 'Ruby' started by Joe Van Dyk, Mar 30, 2005.

  1. Joe Van Dyk

    Joe Van Dyk Guest

    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
    Joe Van Dyk, Mar 30, 2005
    #1
    1. Advertising

  2. Joe Van Dyk

    Joe Van Dyk Guest

    I've attatched code and test code at
    http://rafb.net/paste/results/2Rj4rb87.html , 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 <> 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
    >
    Joe Van Dyk, Mar 31, 2005
    #2
    1. Advertising

  3. Joe Van Dyk

    Ben Giddings Guest

    Joe Van Dyk wrote:
    > I've attatched code and test code at
    > http://rafb.net/paste/results/2Rj4rb87.html , 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 <> 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.html#M001773

    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/Process.html

    Ben
    Ben Giddings, Mar 31, 2005
    #3
  4. Joe Van Dyk

    Saynatkari Guest

    In data 3/31/2005, "Joe Van Dyk" <> ha scritto:
    >I've attatched code and test code at
    >http://rafb.net/paste/results/2Rj4rb87.html , 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 <> 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
    Saynatkari, Mar 31, 2005
    #4
  5. Joe Van Dyk

    Sam Roberts Guest

    Wrote Joe Van Dyk <>, 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 <>
    Sam Roberts, Mar 31, 2005
    #5
  6. 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 <> 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.
    Brian Candler, Mar 31, 2005
    #6
  7. Joe Van Dyk

    Csaba Henk Guest

    On 2005-03-30, Joe Van Dyk <> 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
    Csaba Henk, Apr 2, 2005
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. ALuPin
    Replies:
    0
    Views:
    770
    ALuPin
    Sep 21, 2004
  2. Ted R
    Replies:
    3
    Views:
    822
    Rob Young
    Oct 23, 2004
  3. Brendan Reynolds
    Replies:
    0
    Views:
    361
    Brendan Reynolds
    Jun 24, 2005
  4. jpock76
    Replies:
    0
    Views:
    600
    jpock76
    Aug 23, 2010
  5. Jake Barnes
    Replies:
    2
    Views:
    299
Loading...

Share This Page