Capturing System Call Return Values?

Discussion in 'Ruby' started by Tyler Knappe, Jun 19, 2009.

  1. Tyler Knappe

    Tyler Knappe Guest

    I'm attempting to use Ruby to make system calls (in this case python
    scripts) which return values, that I then hand off to Ruby on Rails to
    populate a webpage. However, I've run into a problem with capturing the
    return values of system calls.

    Using system () only returns whether the command was executed
    successfully.

    Using `[system call]` captures stdout, which works, but only if I then
    chomp on the string returned. I would then have to make some
    assumptions about the size of each value returned (I really see this
    being error prone).

    Using systemu (http://codeforpeople.com/lib/ruby/systemu/) allows me to
    capture stdout, stderror, and status. Not returned values.

    One work around is to call multiple python scripts, but this could
    become very expensive very fast, because I'm querying a database (plus
    one call returns all the values I need).

    Ideally, I would be able to return an array of values from my python
    script then use them in ruby to populate the webpage. Is this possible?
    --
    Posted via http://www.ruby-forum.com/.
     
    Tyler Knappe, Jun 19, 2009
    #1
    1. Advertising

  2. Tyler Knappe

    Roger Pack Guest

    Roger Pack, Jun 19, 2009
    #2
    1. Advertising

  3. Tyler Knappe

    Tyler Knappe Guest

    Roger Pack wrote:
    > Tyler Knappe wrote:
    >> I'm attempting to use Ruby to make system calls (in this case python
    >> scripts) which return values, that I then hand off to Ruby on Rails to
    >> populate a webpage. However, I've run into a problem with capturing the
    >> return values of system calls.

    >
    > appears to be $?, from some google work
    > http://74.125.155.132/search?q=cach...les&cd=1&hl=en&ct=clnk&gl=us&client=firefox-a


    $? exit status of last executed child process

    I don't think is quite correct. I tried it and was returned a value of
    0.

    I've found a work around by splitting the returned string using
    [string].split(' ') but this isn't as elegant as I had hoped.
    --
    Posted via http://www.ruby-forum.com/.
     
    Tyler Knappe, Jun 19, 2009
    #3
  4. On 19.06.2009 20:52, Tyler Knappe wrote:
    > Roger Pack wrote:
    >> Tyler Knappe wrote:
    >>> I'm attempting to use Ruby to make system calls (in this case python
    >>> scripts) which return values,


    The term "system call" is usually used to denote calls of functions in
    the system library (e.g. open(), read(), fork()). What you mean would
    rather be called an "external process". (Of course that's done via a
    system call as well, but this is just one of a multitude of available
    system calls.)

    >>> that I then hand off to Ruby on Rails to
    >>> populate a webpage. However, I've run into a problem with capturing the
    >>> return values of system calls.

    >> appears to be $?, from some google work
    >> http://74.125.155.132/search?q=cach...les&cd=1&hl=en&ct=clnk&gl=us&client=firefox-a

    >
    > $? exit status of last executed child process
    >
    > I don't think is quite correct. I tried it and was returned a value of
    > 0.


    Why would that mean that the statement above is not correct?

    > I've found a work around by splitting the returned string using
    > [string].split(' ') but this isn't as elegant as I had hoped.


    Now I am not sure what you want: are you interested in the exit status
    of a process that was executed? E.g.

    irb(main):010:0> system "false"
    => false
    irb(main):011:0> $?
    => #<Process::Status: pid 4008 exit 1>
    irb(main):012:0> system "echo", "test"
    test
    => true
    irb(main):013:0> $?
    => #<Process::Status: pid 1228 exit 0>
    irb(main):014:0>

    Or do you mean the output of an external process, e.g.

    irb(main):001:0> dir = `ls -dl`
    => "drwxrwxrwt+ 2 robert Benutzer 0 Jun 19 21:53 .\n"
    irb(main):002:0>

    Your last statement seems to indicate the latter.

    Kind regards

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
     
    Robert Klemme, Jun 19, 2009
    #4
  5. Tyler Knappe

    list. rb Guest

    class Task
    attr_accessor :cmd, :pid, :eek:utput, :exitstatus, :thread
    def initialize(cmd)
    @cmd =3D cmd
    queue =3D Queue.new
    @thread =3D Thread.new(queue) {|q|
    pipe =3D IO.popen(cmd + " 2>&1")
    q.push(pipe)
    q.push(pipe.pid)
    self.pid =3D pipe.pid
    begin
    self.output =3D pipe.readlines
    pipe.close
    self.exitstatus =3D $?.exitstatus
    rescue =3D> e
    q.push e
    end
    }
    queue.clear
    end
    def join
    thread.join
    end
    end

    task =3D Task.new("ruby -e 'sleep 3 and puts Time.now'")
    task.join
    p task

    On Fri, Jun 19, 2009 at 4:05 PM, Robert Klemme
    <>wrote:

    > On 19.06.2009 20:52, Tyler Knappe wrote:
    >
    >> Roger Pack wrote:
    >>
    >>> Tyler Knappe wrote:
    >>>
    >>>> I'm attempting to use Ruby to make system calls (in this case python
    >>>> scripts) which return values,
    >>>>
    >>>

    > The term "system call" is usually used to denote calls of functions in th=

    e
    > system library (e.g. open(), read(), fork()). What you mean would rather=

    be
    > called an "external process". (Of course that's done via a system call a=

    s
    > well, but this is just one of a multitude of available system calls.)
    >
    > that I then hand off to Ruby on Rails to
    >>>> populate a webpage. However, I've run into a problem with capturing t=

    he
    >>>> return values of system calls.
    >>>>
    >>> appears to be $?, from some google work
    >>>
    >>> http://74.125.155.132/search?q=3Dcache:lNLxDxyXbj4J:www.rubyist.net/~sl=

    agell/ruby/globalvars.html+ruby+global+variables&cd=3D1&hl=3Den&ct=3Dclnk&g=
    l=3Dus&client=3Dfirefox-a<http://74.125.155.132/search?q=3Dcache:lNLxDxyXbj=
    4J:www.rubyist.net/~slagell/ruby/globalvars.html ruby global variables&cd=
    =3D1&hl=3Den&ct=3Dclnk&gl=3Dus&client=3Dfirefox-a>
    >>>

    >>
    >> $? exit status of last executed child process
    >>
    >> I don't think is quite correct. I tried it and was returned a value of =

    0.
    >>

    >
    > Why would that mean that the statement above is not correct?
    >
    > I've found a work around by splitting the returned string using
    >> [string].split(' ') but this isn't as elegant as I had hoped.
    >>

    >
    > Now I am not sure what you want: are you interested in the exit status of=

    a
    > process that was executed? E.g.
    >
    > irb(main):010:0> system "false"
    > =3D> false
    > irb(main):011:0> $?
    > =3D> #<Process::Status: pid 4008 exit 1>
    > irb(main):012:0> system "echo", "test"
    > test
    > =3D> true
    > irb(main):013:0> $?
    > =3D> #<Process::Status: pid 1228 exit 0>
    > irb(main):014:0>
    >
    > Or do you mean the output of an external process, e.g.
    >
    > irb(main):001:0> dir =3D `ls -dl`
    > =3D> "drwxrwxrwt+ 2 robert Benutzer 0 Jun 19 21:53 .\n"
    > irb(main):002:0>
    >
    > Your last statement seems to indicate the latter.
    >
    > Kind regards
    >
    > robert
    >
    > --
    > remember.guy do |as, often| as.you_can - without end
    > http://blog.rubybestpractices.com/
    >
    >
     
    list. rb, Jun 19, 2009
    #5
  6. Tyler Knappe

    list. rb Guest

    On Fri, Jun 19, 2009 at 5:26 PM, list. rb <> wrote:

    > class Task
    > attr_accessor :cmd, :pid, :eek:utput, :exitstatus, :thread
    > def initialize(cmd)
    > @cmd =3D cmd
    > queue =3D Queue.new
    > @thread =3D Thread.new(queue) {|q|
    > pipe =3D IO.popen(cmd + " 2>&1")
    > q.push(pipe)
    > q.push(pipe.pid)
    > self.pid =3D pipe.pid
    > begin
    > self.output =3D pipe.readlines
    > pipe.close
    > self.exitstatus =3D $?.exitstatus
    > rescue =3D> e
    > q.push e
    > end
    > }
    > queue.clear
    > end
    > def join
    > thread.join
    > end
    > end
    >
    > task =3D Task.new("ruby -e 'sleep 3 and puts Time.now'")
    > task.join
    > p task
    >
    > On Fri, Jun 19, 2009 at 4:05 PM, Robert Klemme
    > <>wrote:
    >
    > > On 19.06.2009 20:52, Tyler Knappe wrote:
    > >
    > >> Roger Pack wrote:
    > >>
    > >>> Tyler Knappe wrote:
    > >>>
    > >>>> I'm attempting to use Ruby to make system calls (in this case python
    > >>>> scripts) which return values,
    > >>>>
    > >>>

    > > The term "system call" is usually used to denote calls of functions in

    > the
    > > system library (e.g. open(), read(), fork()). What you mean would rath=

    er
    > be
    > > called an "external process". (Of course that's done via a system call

    > as
    > > well, but this is just one of a multitude of available system calls.)
    > >
    > > that I then hand off to Ruby on Rails to
    > >>>> populate a webpage. However, I've run into a problem with capturing

    > the
    > >>>> return values of system calls.
    > >>>>
    > >>> appears to be $?, from some google work
    > >>>
    > >>>

    > http://74.125.155.132/search?q=3Dcache:lNLxDxyXbj4J:www.rubyist.net/~slag=

    ell/ruby/globalvars.html+ruby+global+variables&cd=3D1&hl=3Den&ct=3Dclnk&gl=
    =3Dus&client=3Dfirefox-a<http://74.125.155.132/search?q=3Dcache:lNLxDxyXbj4=
    J:www.rubyist.net/~slagell/ruby/globalvars.html ruby global variables&cd=
    =3D1&hl=3Den&ct=3Dclnk&gl=3Dus&client=3Dfirefox-a>
    > <
    > http://74.125.155.132/search?q=3Dcache:lNLxDxyXbj4J:www.rubyist.net/~sl=

    agell/ruby/globalvars.html+ruby+global+variables&cd=3D1&hl=3Den&ct=3Dclnk&g=
    l=3Dus&client=3Dfirefox-a
    > >
    > >>>
    > >>
    > >> $? exit status of last executed child process
    > >>
    > >> I don't think is quite correct. I tried it and was returned a value o=

    f
    > 0.
    > >>

    > >
    > > Why would that mean that the statement above is not correct?
    > >
    > > I've found a work around by splitting the returned string using
    > >> [string].split(' ') but this isn't as elegant as I had hoped.
    > >>

    > >
    > > Now I am not sure what you want: are you interested in the exit status =

    of
    > a
    > > process that was executed? E.g.
    > >
    > > irb(main):010:0> system "false"
    > > =3D> false
    > > irb(main):011:0> $?
    > > =3D> #<Process::Status: pid 4008 exit 1>
    > > irb(main):012:0> system "echo", "test"
    > > test
    > > =3D> true
    > > irb(main):013:0> $?
    > > =3D> #<Process::Status: pid 1228 exit 0>
    > > irb(main):014:0>
    > >
    > > Or do you mean the output of an external process, e.g.
    > >
    > > irb(main):001:0> dir =3D `ls -dl`
    > > =3D> "drwxrwxrwt+ 2 robert Benutzer 0 Jun 19 21:53 .\n"
    > > irb(main):002:0>
    > >
    > > Your last statement seems to indicate the latter.
    > >
    > > Kind regards
    > >
    > > robert
    > >
    > > --
    > > remember.guy do |as, often| as.you_can - without end
    > > http://blog.rubybestpractices.com/
    > >
    > >

    >




    Whoops, I top posted


    class Task
    attr_accessor :cmd, :pid, :eek:utput, :exitstatus, :thread
    def initialize(cmd)
    @cmd =3D cmd
    queue =3D Queue.new
    @thread =3D Thread.new(queue) {|q|
    pipe =3D IO.popen(cmd + " 2>&1")
    q.push(pipe)
    q.push(pipe.pid)
    self.pid =3D pipe.pid
    begin
    self.output =3D pipe.readlines
    pipe.close
    self.exitstatus =3D $?.exitstatus
    rescue =3D> e
    q.push e
    end
    }
    queue.clear
    end
    def join
    thread.join
    end
    end

    task =3D Task.new("ruby -e 'sleep 3 and puts Time.now'")
    task.join
    p task
     
    list. rb, Jun 19, 2009
    #6
  7. On 19.06.2009 23:28, list. rb wrote:

    > Whoops, I top posted


    And now you also forgot to trim your quotes - ts ts ts... :)

    robert

    --
    remember.guy do |as, often| as.you_can - without end
    http://blog.rubybestpractices.com/
     
    Robert Klemme, Jun 19, 2009
    #7
  8. > I've found a work around by splitting the returned string using
    > [string].split(' ') but this isn't as elegant as I had hoped.


    I wrote a library called Rye to solve this problem. It might be some
    like what you're looking for. Here's an example of running local
    external processes:

    ret = Rye.shell('script.py', 'arg1', 'arg2')
    p ret.stdout # => ['line1', 'line2']
    p ret.exit_code # => 0
    p ret.stderr # => nil
    p ret.class # => Rye::Rap

    There is also an object oriented interface for executing remote
    processes via SSH.

    Codes: http://github.com/delano/rye/
    RDocs: http://rye.rubyforge.org/

    Delano
     
    Delano Mandelbaum, Jun 20, 2009
    #8
  9. Tyler Knappe

    list. rb Guest

    [Note: parts of this message were removed to make it a legal post.]

    One thin wanted to do but never got around to it - was to return the output
    in a call back as each line was written to..

    On Fri, Jun 19, 2009 at 9:11 PM, Delano Mandelbaum <>wrote:

    > > I've found a work around by splitting the returned string using
    > > [string].split(' ') but this isn't as elegant as I had hoped.

    >
    > I wrote a library called Rye to solve this problem. It might be some
    > like what you're looking for. Here's an example of running local
    > external processes:
    >
    > ret = Rye.shell('script.py', 'arg1', 'arg2')
    > p ret.stdout # => ['line1', 'line2']
    > p ret.exit_code # => 0
    > p ret.stderr # => nil
    > p ret.class # => Rye::Rap
    >
    > There is also an object oriented interface for executing remote
    > processes via SSH.
    >
    > Codes: http://github.com/delano/rye/
    > RDocs: http://rye.rubyforge.org/
    >
    > Delano
    >
    >
    >
     
    list. rb, Jun 20, 2009
    #9
  10. Tyler Knappe

    list. rb Guest

    [Note: parts of this message were removed to make it a legal post.]

    > One thin wanted to do but never got around to it - was to return the
    > output in a call back as each line was written to..
    >
    >
    > On Fri, Jun 19, 2009 at 9:11 PM, Delano Mandelbaum <>wrote:
    >
    >> > I've found a work around by splitting the returned string using
    >> > [string].split(' ') but this isn't as elegant as I had hoped.

    >>
    >> I wrote a library called Rye to solve this problem. It might be some
    >> like what you're looking for. Here's an example of running local
    >> external processes:
    >>
    >> ret = Rye.shell('script.py', 'arg1', 'arg2')
    >> p ret.stdout # => ['line1', 'line2']
    >> p ret.exit_code # => 0
    >> p ret.stderr # => nil
    >> p ret.class # => Rye::Rap
    >>
    >> There is also an object oriented interface for executing remote
    >> processes via SSH.
    >>
    >> Codes: http://github.com/delano/rye/
    >> RDocs: http://rye.rubyforge.org/
    >>
    >> Delano
    >>

    >



    Second attempt at correcting a top post ;-) grrrmail

    One thin wanted to do but never got around to it - was to return the output
    in a call back as each line was written to..
     
    list. rb, Jun 20, 2009
    #10

  11. > One thin wanted to do but never got around to it  - was to return the output
    > in a call back as each line was written to..


    That's coming in Rye 0.9 :] (currently 0.7.6)
     
    Delano Mandelbaum, Jun 20, 2009
    #11
  12. Tyler Knappe

    Tyler Knappe Guest


    >
    > Why would that mean that the statement above is not correct?
    >


    Revisiting this, here is what I am trying to do:

    path = "python [..path..]/test.py"

    print path + "\n"

    test = %x[python [..path..]/test.py]

    print test

    testing = %x[uptime]

    print testing


    Here is the output:

    python [..path..]/test.py
    Testing! my script
    2nd line
    8:20am up 181 days 20:55, 7 users, load average: 0.00, 0.00, 0.00

    However, what I was expecting from the test variable was this:

    print "Testing! my script "
    print "2nd line"

    def returnValue():
    return True

    returnValue()

    Where I was expecting to see test = True. The return value of the
    system call is not being capture when I call a python script, yet IS
    when a 'system call' is made.

    Anyone have any insight into this?
    --
    Posted via http://www.ruby-forum.com/.
     
    Tyler Knappe, Jun 23, 2009
    #12
  13. Tyler Knappe

    Roger Pack Guest

    > Anyone have any insight into this?

    Hmm.

    >> `bad`

    (irb):1: command not found: bad
    => ""
    >> $?

    => #<Process::Status: pid=27331,exited(127)>
    >> system("bad")

    => false
    irb(main):004:0> $?
    => #<Process::Status: pid=27335,exited(127)>

    Appears a little buggy on windows for some reason.

    C:\dev\blade_copy>irb
    >> `bad`
    >> $?

    => #<Process::Status: pid=5636,exited(0)> # this is wrong
    >> system("bad")

    => false
    >> $?

    => #<Process::Status: pid=0,exited(127)>
    >> `bad`
    >> $?

    => #<Process::Status: pid=0,exited(127)> # and now it's right. Odd.

    -=r
    --
    Posted via http://www.ruby-forum.com/.
     
    Roger Pack, Jun 23, 2009
    #13
  14. Tyler Knappe

    Tyler Knappe Guest

    Roger Pack wrote:
    >
    > Hmm.
    >
    >>> `bad`

    > (irb):1: command not found: bad
    > => ""
    >>> $?

    > => #<Process::Status: pid=27331,exited(127)>
    >>> system("bad")

    > => false
    > irb(main):004:0> $?
    > => #<Process::Status: pid=27335,exited(127)>
    >
    > Appears a little buggy on windows for some reason.
    >
    > C:\dev\blade_copy>irb
    >>> `bad`
    >>> $?

    > => #<Process::Status: pid=5636,exited(0)> # this is wrong
    >>> system("bad")

    > => false
    >>> $?

    > => #<Process::Status: pid=0,exited(127)>
    >>> `bad`
    >>> $?

    > => #<Process::Status: pid=0,exited(127)> # and now it's right. Odd.
    >
    > -=r


    irb(main):008:0> path = "python [..path..]/test.py" => "python
    [..path..]/test.py"
    irb(main):009:0> test = %x[#{path}]
    => "Testing! my script \n2nd line\n"
    irb(main):010:0> test
    => "Testing! my script \n2nd line\n"
    irb(main):011:0> $?
    => #<Process::Status: pid=22782,exited(0)>
    irb(main):012:0> test = `python [..path..]/test.py`
    => "Testing! my script \n2nd line\n"
    irb(main):013:0> test
    => "Testing! my script \n2nd line\n"
    irb(main):014:0> $?
    => #<Process::Status: pid=22826,exited(0)>
    irb(main):015:0>

    test =/= True in either case, which is what I was looking for, nor is
    $?.
    --
    Posted via http://www.ruby-forum.com/.
     
    Tyler Knappe, Jun 23, 2009
    #14
  15. Tyler Knappe

    Roger Pack Guest

    > irb(main):008:0> path = "python [..path..]/test.py" => "python
    > [..path..]/test.py"
    > irb(main):009:0> test = %x[#{path}]
    > => "Testing! my script \n2nd line\n"
    > irb(main):010:0> test
    > => "Testing! my script \n2nd line\n"
    > irb(main):011:0> $?
    > => #<Process::Status: pid=22782,exited(0)>
    > irb(main):012:0> test = `python [..path..]/test.py`
    > => "Testing! my script \n2nd line\n"
    > irb(main):013:0> test
    > => "Testing! my script \n2nd line\n"
    > irb(main):014:0> $?
    > => #<Process::Status: pid=22826,exited(0)>
    > irb(main):015:0>
    >
    > test =/= True in either case, which is what I was looking for, nor is
    > $?.


    So did that answer your question? If not maybe you can help me
    understand more what was trying to happen here.
    Cheers.
    -=r
    --
    Posted via http://www.ruby-forum.com/.
     
    Roger Pack, Jun 23, 2009
    #15
  16. Tyler Knappe

    Tyler Knappe Guest

    Roger Pack wrote:
    >> irb(main):008:0> path = "python [..path..]/test.py" => "python
    >> [..path..]/test.py"
    >> irb(main):009:0> test = %x[#{path}]
    >> => "Testing! my script \n2nd line\n"
    >> irb(main):010:0> test
    >> => "Testing! my script \n2nd line\n"
    >> irb(main):011:0> $?
    >> => #<Process::Status: pid=22782,exited(0)>
    >> irb(main):012:0> test = `python [..path..]/test.py`
    >> => "Testing! my script \n2nd line\n"
    >> irb(main):013:0> test
    >> => "Testing! my script \n2nd line\n"
    >> irb(main):014:0> $?
    >> => #<Process::Status: pid=22826,exited(0)>
    >> irb(main):015:0>
    >>
    >> test =/= True in either case, which is what I was looking for, nor is
    >> $?.

    >
    > So did that answer your question? If not maybe you can help me
    > understand more what was trying to happen here.
    > Cheers.
    > -=r


    No, I had expected to see test == True, as my python script returns
    True. All I see is ruby capturing all stdout and storing it in test.

    I can see where the confusion is coming in, lets say my python script
    instead of returning true, returns an array of values. I want test to
    equal that array of values.
    --
    Posted via http://www.ruby-forum.com/.
     
    Tyler Knappe, Jun 23, 2009
    #16
  17. Tyler Knappe

    Roger Pack Guest


    > Where I was expecting to see test = True. The return value of the
    > system call is not being capture when I call a python script, yet IS
    > when a 'system call' is made.


    I think the confusion comes from this:

    >> system("python test.py")

    Testing! my script
    2nd line
    => true

    that last true means "the command returned a value of 0" and is a ruby
    true

    if you want the output *and* its success value then you'll need to use

    >> %x[python test.py]

    => "Testing! my script \n2nd line\nTrue\n"
    >> $?.exitstatus == 0

    => true

    There's your true.

    If you want to get the last thing the python script outputs then
    [pretend last line is "print returnValue()"]

    it'll be something like %x[python test.py].split("\n")[-1]

    Maybe one of those will help you. Or use Rye which appears to do that
    in a class oriented way.
    -=r
    --
    Posted via http://www.ruby-forum.com/.
     
    Roger Pack, Jun 23, 2009
    #17
  18. [Note: parts of this message were removed to make it a legal post.]

    >
    >
    >
    > No, I had expected to see test == True, as my python script returns
    > True. All I see is ruby capturing all stdout and storing it in test.
    >
    > I can see where the confusion is coming in, lets say my python script
    > instead of returning true, returns an array of values. I want test to
    > equal that array of values.
    > --
    > Posted via http://www.ruby-forum.com/.
    >
    >

    You are expecting a program written in one language to return objects to a
    calling program written in another language ... sorry to say, but it just
    doesn't work that way. It certainly would be nice, though, I have to admit.

    The closest you are going to get is to get the python program to print out a
    string of valid ruby code, make the calling ruby code somehow extract this
    line of output from all the other potential lines of output the python
    program might generate and then maybe eval it in the calling program.

    Or maybe somebody has written some CORBA bindings for ruby? Ha, ha, just
    kidding ... ;)

    Good luck ...

    -Doug Seifert
     
    Douglas Seifert, Jun 24, 2009
    #18
    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. Tony Fields
    Replies:
    0
    Views:
    478
    Tony Fields
    Dec 9, 2004
  2. Greenhorn
    Replies:
    15
    Views:
    833
    Keith Thompson
    Mar 6, 2005
  3. oscartheduck

    capturing system exit status

    oscartheduck, Apr 2, 2007, in forum: Python
    Replies:
    1
    Views:
    371
    Michael Hoffman
    Apr 2, 2007
  4. Sohail Somani
    Replies:
    5
    Views:
    642
    Sohail Somani
    May 7, 2009
  5. Venks
    Replies:
    10
    Views:
    231
    MonkeeSage
    Dec 7, 2007
Loading...

Share This Page