Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.ruby > #2499 > unrolled thread
| Started by | mpurdy <mpurdy1973usergroups@gmail.com> |
|---|---|
| First post | 2011-04-07 20:58 -0700 |
| Last post | 2011-04-08 18:48 -0700 |
| Articles | 5 — 3 participants |
Back to article view | Back to comp.lang.ruby
reading and writing to child process with streams in ruby mpurdy <mpurdy1973usergroups@gmail.com> - 2011-04-07 20:58 -0700
Re: reading and writing to child process with streams in ruby "Y. NOBUOKA" <nobuoka@r-definition.com> - 2011-04-08 03:03 -0500
Re: reading and writing to child process with streams in ruby mpurdy <mpurdy1973usergroups@gmail.com> - 2011-04-08 18:44 -0700
Re: reading and writing to child process with streams in ruby Brian Candler <b.candler@pobox.com> - 2011-04-08 08:32 -0500
Re: reading and writing to child process with streams in ruby mpurdy <mpurdy1973usergroups@gmail.com> - 2011-04-08 18:48 -0700
| From | mpurdy <mpurdy1973usergroups@gmail.com> |
|---|---|
| Date | 2011-04-07 20:58 -0700 |
| Subject | reading and writing to child process with streams in ruby |
| Message-ID | <09ce70f0-118a-4e4d-82f1-7d88436233ff@l39g2000yqh.googlegroups.com> |
i am trying to fork a process to run a simple script which requires a
username and password. i made a test case with a simple bash script
and a simple ruby script; however, the ruby script hangs in
stdout.read???
i am new to ruby, so i am assuming i am doing something wrong :-) can
anyone help?
----------------------------------------------------------------------
bash script
----------------------------------------------------------------------
#! /bin/bash
sleep 3
echo -n "username: "
read -e USERNAME
echo -n "password: "
read -e PASSWORD
echo "running your script now for $USERNAME with password $PASSWORD"
echo 'doing something...'
sleep 3
echo 'end doing something...quiting'
exit 0
----------------------------------------------------------------------
ruby script
----------------------------------------------------------------------
require 'open3'
cmd = "./myScript.bash"
#cmd = "gpg --list-keys"
begin
stdin, stdout, stderr = Open3.popen3 cmd
done = 0
until done == 1
begin
line = stdout.read
print "#{line}"
puts line.eql?("username: ")
if line.eql?("username: ")
puts "myuser"
stdin.write "myuser\n"
line = stdout.read
if line.eql?("password: ")
puts "mypassword"
stdin.write "mypassword\n"
done = 1
end
puts "im here!"
end
end
end
end
[toc] | [next] | [standalone]
| From | "Y. NOBUOKA" <nobuoka@r-definition.com> |
|---|---|
| Date | 2011-04-08 03:03 -0500 |
| Message-ID | <BANLkTik+832FqXp-3oAD=YtqoXtwvaBL4Q@mail.gmail.com> |
| In reply to | #2499 |
Hi,
Using IO#readpartial [1] instead of IO#read, you'll see the ruby
script run as expected.
However, I don't know if this is the best way or not.
[1] http://www.ruby-doc.org/core/classes/IO.html#M000917
----------------------------------------------------------------------
ruby script
----------------------------------------------------------------------
require 'open3'
cmd = "./myScript.bash"
#cmd = "gpg --list-keys"
begin
stdin, stdout, stderr = Open3.popen3 cmd
p stdin, stdout, stderr
done = 0
until done == 1
begin
# using IO#readpartial instead of IO#read
line = stdout.readpartial( 4096 )
puts "#{line}"
puts line.eql?("username: ")
if line.eql?("username: ")
puts "myuser"
stdin.write "myuser\n"
# using IO#readpartial instead of IO#read
line = stdout.readpartial( 4096 )
if line.eql?("password: ")
puts "mypassword"
stdin.write "mypassword\n"
done = 1
end
puts "im here!"
end
rescue => err
p err
end
end
end
--
信岡 裕也 (NOBUOKA Yuya)
[toc] | [prev] | [next] | [standalone]
| From | mpurdy <mpurdy1973usergroups@gmail.com> |
|---|---|
| Date | 2011-04-08 18:44 -0700 |
| Message-ID | <96e1f088-76f7-4ee1-9d2e-a8b9d8f22d7b@q36g2000yqn.googlegroups.com> |
| In reply to | #2518 |
On Apr 8, 4:03 am, "Y. NOBUOKA" <nobu...@r-definition.com> wrote:
> Hi,
>
> Using IO#readpartial [1] instead of IO#read, you'll see the ruby
> script run as expected.
> However, I don't know if this is the best way or not.
>
> [1]http://www.ruby-doc.org/core/classes/IO.html#M000917
>
> ----------------------------------------------------------------------
> ruby script
> ----------------------------------------------------------------------
> require 'open3'
>
> cmd = "./myScript.bash"
> #cmd = "gpg --list-keys"
> begin
> stdin, stdout, stderr = Open3.popen3 cmd
>
> p stdin, stdout, stderr
> done = 0
> until done == 1
> begin
> # using IO#readpartial instead of IO#read
> line = stdout.readpartial( 4096 )
> puts "#{line}"
> puts line.eql?("username: ")
> if line.eql?("username: ")
> puts "myuser"
> stdin.write "myuser\n"
> # using IO#readpartial instead of IO#read
> line = stdout.readpartial( 4096 )
> if line.eql?("password: ")
> puts "mypassword"
> stdin.write "mypassword\n"
> done = 1
> end
> puts "im here!"
> end
> rescue => err
> p err
> end
> end
> end
>
> --
> 信岡 裕也 (NOBUOKA Yuya)
thanx that did work; however, i after doing more research i agree this
is not the best way. i am a c/c++, java/groovy guy...this ruby stuff
is all new to me; however, after day one; i like it:-)
[toc] | [prev] | [next] | [standalone]
| From | Brian Candler <b.candler@pobox.com> |
|---|---|
| Date | 2011-04-08 08:32 -0500 |
| Message-ID | <25ff3d42fe12472e3f3c8ea44c2dbc19@ruby-forum.com> |
| In reply to | #2499 |
mpurdy wrote in post #991644: > echo -n "username: " You are sending just "username: " without a trailing newline. > line = stdout.read Here you are reading from stdout until the end-of-file (i.e. until the other side terminates or closes the file). This will wait forever. Two possible solutions: 1. Change your shell script to send data ending with a newline, then use 'gets' in the ruby code. 2. More generally, use expect.rb in the standard library. Then you can wait for a particular sequence of characters, e.g. /name: /, before continuing. HTH, Brian. -- Posted via http://www.ruby-forum.com/.
[toc] | [prev] | [next] | [standalone]
| From | mpurdy <mpurdy1973usergroups@gmail.com> |
|---|---|
| Date | 2011-04-08 18:48 -0700 |
| Message-ID | <123f302a-0256-4c0c-b7b2-0c540d414f7f@k30g2000yqb.googlegroups.com> |
| In reply to | #2532 |
On Apr 8, 9:32 am, Brian Candler <b.cand...@pobox.com> wrote:
> mpurdy wrote in post #991644:
>
> > echo -n "username: "
>
> You are sending just "username: " without a trailing newline.
>
> > line = stdout.read
>
> Here you are reading from stdout until the end-of-file (i.e. until the
> other side terminates or closes the file). This will wait forever.
>
> Two possible solutions:
>
> 1. Change your shell script to send data ending with a newline, then use
> 'gets' in the ruby code.
>
> 2. More generally, use expect.rb in the standard library. Then you can
> wait for a particular sequence of characters, e.g. /name: /, before
> continuing.
>
> HTH,
>
> Brian.
>
> --
> Posted viahttp://www.ruby-forum.com/.
thanx, i looked into it and rewrote the script using the IO.expect and
it worked good. here is my scripts now:
(note: this is just to have an example for myself and team; we will
using ssh so all the passwords will be protected :-)
----------------------------------------------------------------------
bash script
----------------------------------------------------------------------
#! /bin/bash
echo -n "username: "
read -e USERNAME
echo -n "password: "
read -e PASSWORD
echo "running your script now for $USERNAME with password $PASSWORD"
echo 'doing something...'
sleep 1
echo 'end doing something...quiting'
exit 0
----------------------------------------------------------------------
ruby script
----------------------------------------------------------------------
require 'pty' # found in ruby source @ /ext/pty
require 'expect' # found in ruby source @ /ext/pty/lib/expect.rb
#buffer stores the output from the child process
buffer = ""
# spawn a child process (fork)
PTY.spawn("./myScript.bash") do |output, input, pid|
input.sync = true
#set the expect verbosity flag to false or you will get output from
expect
$expect_verbose = false
#get user from environment if posible
if !ENV['USER'].nil?
username = ENV['USER']
else
username = 'guest'
end
#expect the username prompt and return the username
output.expect('username: ') do
input.puts(username)
end
#expect the password prompt and return the password
output.expect('password: ') do
input.puts 'thePassword'
end
#throw away the password comming back to thru the output (note: you
still get the '\n')
output.expect('thePassword') do
end
#read all the output from the process and put it in a buffer for
later
#keep reading until the EOFError exception is thrown
done = 0
while done == 0
begin
buffer += output.readpartial(1024)
rescue EOFError
done = 1
end
end
end
puts "myExcept.rb script ran myScript.bash the results are: \n
#{buffer}"
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.ruby
csiph-web