Forum: Ruby behavior of 'Open3.popen3' is different when use ruby 1.8.6 and 1.9.3, any solution?

7b3d60a2de005a458e45f2722345f3c6?d=identicon&s=25 Previn Lin (previn)
on 2013-10-23 09:18
#!/usr/bin/env ruby

require 'open3'

x = 'abc'
stdin, stdout, stderr = Open3.popen3("#{x}")
puts "go on running ..."

'abc' is an unix command that doesn't exist.

Use ruby 1.8.6
The error run popen3 stored in stderr, and the error don't show on
screen, then script will go on to output "go on running ..."

Use buby 1.9.3
The error run popen3 will show on screen, and the script exit directly

I want popen3 work as the manner when use 1.8.6, ie.(don't show errors
on screen but just store it in stderr, and script can go on running
instead of exiting), is there any method can do this in 1.9.3?
B11f10c4cd9d53970e7be20caa43f940?d=identicon&s=25 Tanaka Akira (Guest)
on 2013-10-23 11:32
(Received via mailing list)
2013/10/23 Previn Lin <lists@ruby-forum.com>:

> I want popen3 work as the manner when use 1.8.6, ie.(don't show errors
> on screen but just store it in stderr, and script can go on running
> instead of exiting), is there any method can do this in 1.9.3?

Add ";" at the end of the command.

  stdin, stdout, stderr = Open3.popen3("#{x};")

This forces Open3.popen3 to use a shell.
Aa082c8b00a50928e5860dcd70bf2368?d=identicon&s=25 tamouse m. (tamouse_m)
on 2013-10-23 19:20
(Received via mailing list)
On Oct 23, 2013, at 2:18 AM, Previn Lin <lists@ruby-forum.com> wrote:

> Use ruby 1.8.6
> The error run popen3 stored in stderr, and the error don't show on
> screen, then script will go on to output "go on running ..."
>
> Use buby 1.9.3
> The error run popen3 will show on screen, and the script exit directly
>
> I want popen3 work as the manner when use 1.8.6, ie.(don't show errors
> on screen but just store it in stderr, and script can go on running
> instead of exiting), is there any method can do this in 1.9.3?

Wrap it in a begin/rescue block, and process the error properly. Since
1.9, spawn (which is what underlies Open3.popen3 (and others) will
execute a command directly, i.e. without calling the shell, if the
command is a single word and contains no spaces or shell characters, or,
if the arguments are single words, or an array of single words.

begin
  si, so, se, wt = Open3.popen3(cmd)
rescue Exception => e
  # process exception here — if the command is not found, you should
have an Errno::ENOENT error
ensure
  # ...
end

In the above, these will have the following results:

cmd = "ls"   →  runs directly from spawn
cmd = "ls -l"  →  runs under shell because of space (a shell char)
cmd = ["ls", "-l"]  → runs directly from spawn
cmd = "asdfasdf" (not a program) → spawn raises ENOENT, caught in rescue
cmd = "asdfasdf;" (not a program, but with shell character) → runs under
shell, shell returns stderr, no exception raised

For my dough, running under the shell adds extra cost, so I just run
directly with spawn, and deal with the exceptions in my script.
7b3d60a2de005a458e45f2722345f3c6?d=identicon&s=25 Previn Lin (previn)
on 2013-10-24 10:04
Tanaka Akira wrote in post #1125314:
> 2013/10/23 Previn Lin <lists@ruby-forum.com>:
>
>> I want popen3 work as the manner when use 1.8.6, ie.(don't show errors
>> on screen but just store it in stderr, and script can go on running
>> instead of exiting), is there any method can do this in 1.9.3?
>
> Add ";" at the end of the command.
>
>   stdin, stdout, stderr = Open3.popen3("#{x};")
>
> This forces Open3.popen3 to use a shell.

Wow, it works, thank you so much!
7b3d60a2de005a458e45f2722345f3c6?d=identicon&s=25 Previn Lin (previn)
on 2013-10-24 10:07
tamouse m. wrote in post #1125396:
> begin
>   si, so, se, wt = Open3.popen3(cmd)
> rescue Exception => e
>   # process exception here — if the command is not found, you should
> have an Errno::ENOENT error
> ensure
>   # ...
> end
>
> In the above, these will have the following results:
>
> cmd = "ls"   →  runs directly from spawn
> cmd = "ls -l"  →  runs under shell because of space (a shell char)
> cmd = ["ls", "-l"]  → runs directly from spawn
> cmd = "asdfasdf" (not a program) → spawn raises ENOENT, caught in rescue
> cmd = "asdfasdf;" (not a program, but with shell character) → runs under
> shell, shell returns stderr, no exception raised
>
> For my dough, running under the shell adds extra cost, so I just run
> directly with spawn, and deal with the exceptions in my script.

Hi tamouse_m,

Thank you so much for your guide with so detailed explanation, I'm more
clear with it now, many thanks.

Previn
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.