Capturing System Call Return Values?

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?

Tyler K. 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=cache:lNLxDxyXbj4J:www.rubyist.net/~slagell/ruby/globalvars.html+ruby+global+variables&cd=1&hl=en&ct=clnk&gl=us&client=firefox-a

Roger P. wrote:

Tyler K. 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=cache:lNLxDxyXbj4J:www.rubyist.net/~slagell/ruby/globalvars.html+ruby+global+variables&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.

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

task = Task.new(“ruby -e ‘sleep 3 and puts Time.now’”)
task.join
p task

On Fri, Jun 19, 2009 at 4:05 PM, Robert K.

On Fri, Jun 19, 2009 at 5:26 PM, list. rb [email protected] wrote:

 begin

thread.join

On 19.06.2009 20:52, Tyler K. wrote:
the

Now I am not sure what you want: are you interested in the exit status of
irb(main):013:0> $?

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, :output, :exitstatus, :thread
def initialize(cmd)
@cmd = cmd
queue = Queue.new
@thread = Thread.new(queue) {|q|
pipe = IO.popen(cmd + " 2>&1")
q.push(pipe)
q.push(pipe.pid)
self.pid = pipe.pid
begin
self.output = pipe.readlines
pipe.close
self.exitstatus = $?.exitstatus
rescue => e
q.push e
end
}
queue.clear
end
def join
thread.join
end
end

task = Task.new(“ruby -e ‘sleep 3 and puts Time.now’”)
task.join
p task

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… :slight_smile:

robert

On 19.06.2009 20:52, Tyler K. wrote:

Roger P. wrote:

Tyler K. 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=cache:lNLxDxyXbj4J:www.rubyist.net/~slagell/ruby/globalvars.html+ruby+global+variables&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

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…

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: GitHub - delano/rye: Safe, parallel access to Unix shells from Ruby
RDocs: http://rye.rubyforge.org/

Delano

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)

like what you’re looking for. Here’s an example of running local

Codes: GitHub - delano/rye: Safe, parallel access to Unix shells from Ruby
RDocs: http://rye.rubyforge.org/

Delano

Second attempt at correcting a top post :wink: 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…

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

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?

Roger P. 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
$?.

Roger P. 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.

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

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

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 … :wink:

Good luck …

-Doug Seifert