Some noob questions

J

John Ydil

Hello Ruby friends!

I'm learning ruby and i already have some problems.

I have a file with Login and Ip address but not on the same line.
Exemple :

Login1
Address1
Login2
Address2
....


I searh a way to extract the IP address when i search the login
search.rb Login2

I know how to search a pattern :

Login= File.open("users" ).each_line.grep( /Login2/ )
puts Login

First question : how can i see the line after ? the line with the Ip
address of that login

Second question : I don't search always the same pattern so i need to
pass an argument to my script. I tried this
Login= File.open("users" ).each_line.grep( /ARGV[0]/ )
puts Login
but it doesn't show anything

Third question : After having the ip address, i need to make an ssh
connection to this address. How can i get a variable to be usable in
system("ssh $variable") ?

Thanks for your help and sorry for my english, i hope it's
understandable.


Ydil
 
R

Robert Klemme

Hello Ruby friends!

I'm learning ruby and i already have some problems.

I have a file with Login and Ip address but not on the same line.
Exemple :

Login1
Address1
Login2
Address2
...


I searh a way to extract the IP address when i search the login
search.rb Login2

I know how to search a pattern :

Login= File.open("users" ).each_line.grep( /Login2/ )
puts Login

First question : how can i see the line after ? the line with the Ip
address of that login

You could use #each_slice for this (see below).
Second question : I don't search always the same pattern so i need to
pass an argument to my script. I tried this
Login= File.open("users" ).each_line.grep( /ARGV[0]/ )
puts Login
but it doesn't show anything

You need string interpolation in the regular expression. In your case
the regexp will match if there is "ARGV0" somewhere in the string -
certainly not what you wanted. :)

If your file only contains login and password alternating you could do

def lookup(file, user)
File.foreach(file).each_slice 2 do |name, pwd|
name.strip!
pwd.strip!
return pwd if user === name
end

# not found
nil
end

So, how does this work? File.foreach(file) without a block creates an
Enumerator, i.e. something that behaves like an Enumerable. With
#each_slice(2) iteration will yield two subsequent values at a time:

irb(main):012:0> (1..10).each_slice 2 do |a| p a end
[1, 2]
[3, 4]
[5, 6]
[7, 8]
[9, 10]
=> nil
irb(main):013:0>

Now we have File.foreach(file) instead of 1..10 so what happens here is
that lines are read from the file and returned in pairs to the block.
The block checks whether there is a match (after removing trailing
newlines) and returns from the method if it finds something.

You can use this with regular expressions *and* Strings because of ===:

pwd = lookup "users", ARGV[0]
pwd = lookup "users", /#{ARGV[0]}/


If you want to do string matching and need to match multiple times
during a single script execution you could as well load the file into a Hash

user_password = Hash[*(File.foreach(file).map {|s| s.chomp})]

This will work only if your file has an even number of lines though.
Third question : After having the ip address, i need to make an ssh
connection to this address. How can i get a variable to be usable in
system("ssh $variable") ?

You can use regular string interpolation

system "ssh #{your_variable}"

AFAIK there is also a SSL / SSH library for Ruby. You should probably
look into that as well.
Thanks for your help and sorry for my english, i hope it's
understandable.

No problem.

Kind regards

robert
 
J

Josh Cheek

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

AFAIK there is also a SSL / SSH library for Ruby. You should probably look
into that as well.
The book "Practical Ruby Gems" suggests net-ssh (
http://gemcutter.org/gems/net-ssh), and has a six page example of a simple
use program that logs onto a remote server with SSH and uses Vim to edit a
text file. It also has an example of net-sftp. (though one of those was
outdated, I think the net-sftp version had changed)
 
B

Brian Candler

John said:
Third question : After having the ip address, i need to make an ssh
connection to this address. How can i get a variable to be usable in
system("ssh $variable") ?

That would be either
system("ssh",variable) # you split the args
or
system("ssh #{variable}" # shell splits the args

But this is probably not what you want, unless you're just using ssh to
execute a single command remotely, and you're using RSA keys so you're
not going to be prompted for a passwords.

Have a look at Net::SSH and Net::SSH::Telnet (the latter wraps Net::SSH
in an API which is a drop-in replacement for Net::Telnet)
 
J

John Ydil

Josh said:
The book "Practical Ruby Gems" suggests net-ssh (
http://gemcutter.org/gems/net-ssh), and has a six page example of a
simple
use program that logs onto a remote server with SSH and uses Vim to edit
a
text file. It also has an example of net-sftp. (though one of those was
outdated, I think the net-sftp version had changed)

Thanks for your help but the ssh command was an exemple :p

In fact, i need to check routes on a linux router. It's a light linux
distribution, i can't install anything.
There is ruby 1.8.2 inside that's why i'm learning how to use it.

New question !

Thanks to Robert, I have my IP address (Youhou) I need to check the
route with this IP address.

the linux command is "ip route get {IP address}"
so my command is : system("ip route get #{ipaddress}") but the result of
this, is just true or false. How can I put the result of my command in a
variable ?


regards,

Ydil
 
A

Aldric Giacomoni

Robert said:
Hmm, maybe it helps that I practice a Japanese martial art. ;-)
Not to completely derail the conversation here (oops?) but, as a
parenthesis.. Which one?
 
J

John Ydil

Hi, me again...

As i said before, I "play" with ruby on a light linux (ruby 1.8.2).
I made my script on my computer (ruby 1.8.7) and move it to my linux.

I works fine on my computer but an error occured when i launch it on my
linux.


Here is my code :

File.foreach("/etc/raddb/users").each_slice 4 do |name, ip, dump, table|
puts name.strip!
puts ip.strip!
puts table.strip!
end

here is the file /etc/raddb/users

login Auth-Type :=Local, User-Password == "bonjour"
Framed-IP-Address = ipaddress,
Fall-Through = No
# table 254


Here is the error :
/test.rb:12:in `foreach': no block given (LocalJumpError)
from ./test.rb:12

I wonder if it's due to the difference between the 2 versions, Do you
have an idea ?
 
A

Aldric Giacomoni

John said:
File.foreach("/etc/raddb/users").each_slice 4 do |name, ip, dump, table|
puts name.strip!
puts ip.strip!
puts table.strip!
end

here is the file /etc/raddb/users

login Auth-Type :=Local, User-Password == "bonjour"
Framed-IP-Address = ipaddress,
Fall-Through = No
# table 254


Here is the error :
./test.rb:12:in `foreach': no block given (LocalJumpError)
from ./test.rb:12

I wonder if it's due to the difference between the 2 versions, Do you
have an idea ?

Well, for this one, a quick look at the documentation will give you the
answer:
http://ruby-doc.org/core/classes/IO.html#M002243

"foreach" expects a block. So you can't really do "each slice" on
"foreach" since you should do "foreach" on ... er ... each line in the
file.
Probably you'll do the foreach, and a slice on that line within the code
block instead.
 
R

Robert Klemme

2010/2/11 Aldric Giacomoni said:
Well, for this one, a quick look at the documentation will give you the
answer:
http://ruby-doc.org/core/classes/IO.html#M002243

"foreach" expects a block. So you can't really do "each slice" on
"foreach" since you should do "foreach" on ... er ... each line in the
file.
Probably you'll do the foreach, and a slice on that line within the code
block instead.

He's on 1.8.2. There you have to do

require 'enumerator'

File.to_enum:)foreach, "/etc/raddb/users").each_slice 4 do |name, ip,
dump, table|
puts name.strip!
puts ip.strip!
puts table.strip!
end

The convenient feature to return an Enumerator from enumerating
methods which expect a block but do not receive it was added in 1.9
and backported to 1.8.7.

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
J

John Ydil

Robert said:
He's on 1.8.2. There you have to do

require 'enumerator'

File.to_enum:)foreach, "/etc/raddb/users").each_slice 4 do |name, ip,
dump, table|
puts name.strip!
puts ip.strip!
puts table.strip!
end

The convenient feature to return an Enumerator from enumerating
methods which expect a block but do not receive it was added in 1.9
and backported to 1.8.7.

Kind regards

robert

I was afraid of this, but :
/test.rb:5:in `require': No such file to load -- enumerator (LoadError)
from ./test.rb:5


Maybe I haven't the full ruby because it's a small linux...
 
R

Robert Klemme

2010/2/11 John Ydil said:
I was afraid of this, but :
./test.rb:5:in `require': No such file to load -- enumerator (LoadError)
=A0 =A0 =A0 =A0from ./test.rb:5


Maybe I haven't the full ruby because it's a small linux...

Oooops! Sorry for the wrong advice. Either that or Enumerator did
not exist in 1.8.2 (which is ancient btw - I cannot remember having
used it).

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
J

John Ydil

Robert said:
Oooops! Sorry for the wrong advice. Either that or Enumerator did
not exist in 1.8.2 (which is ancient btw - I cannot remember having
used it).

Kind regards

robert

So there is no way i can do that in 1.8.2 ?
 
R

Robert Klemme

2010/2/12 John Ydil said:
So there is no way i can do that in 1.8.2 ?

You can write Enumerator yourself. It isn't too hard

Enum =3D Struct.new :inst, :args do
include Enumerable

def each(&b)
inst.send(*args, &b)
self
end
end

class Object
def to_enum(*a)
Enum.new(self, a)
end
end

:)

Kind regards

robert

--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
J

John Ydil

Robert said:
You can write Enumerator yourself. It isn't too hard

Enum = Struct.new :inst, :args do
include Enumerable

def each(&b)
inst.send(*args, &b)
self
end
end

class Object
def to_enum(*a)
Enum.new(self, a)
end
end

:)

Kind regards

robert

Thanks again Robert but (there is always a BUT)....

I copy paste the code you gave me

Enum = Struct.new :inst, :args do
include Enumerable

def each(&b)
inst.send(*args, &b)
self
end
end

class Object
def to_enum(*a)
Enum.new(self, a)
end
end
File.to_enum:)foreach, "/etc/raddb/users").each_slice 4 do
|name, ip, dump, table|
puts name.strip!
puts ip.strip!
puts table.strip!
end

/test.rb:31: undefined method `each_slice' for #<struct Enum inst=File,
args=[:foreach, "/etc/raddb/users"]> (NoMethodError)


I think we progress....
 
R

Robert Klemme

2010/2/12 John Ydil said:
Thanks again Robert but (there is always a BUT)....

I copy paste the code you gave me
=A0 =A0 =A0 =A0File.to_enum:)foreach, "/etc/raddb/users").each_slice 4 do
|name, ip, dump, table|
=A0 =A0 =A0 =A0puts name.strip!
=A0 =A0 =A0 =A0puts ip.strip!
=A0 =A0 =A0 =A0puts table.strip!
end

./test.rb:31: undefined method `each_slice' for #<struct Enum inst=3DFile= ,
args=3D[:foreach, "/etc/raddb/users"]> (NoMethodError)


I think we progress....

Slowly.... I believe #each_slice was added later as well. Oh well.
Can't you just upgrade your Ruby version? That seems a much better
option than trying to retrofit all the new behavior on the old
version.

Kind regards

robert


--=20
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/
 
J

John Ydil

Slowly.... I believe #each_slice was added later as well. Oh well.
Can't you just upgrade your Ruby version? That seems a much better
option than trying to retrofit all the new behavior on the old
version.

Kind regards

robert

I'll try to upgrade.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top