SitePoint Sponsor

User Tag List

Results 1 to 8 of 8

Hybrid View

  1. #1
    SitePoint Member
    Join Date
    Jan 2003
    Posts
    15
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Pushing Results from Exec into an Array

    Anyone know how to push something from 'exec' into an array?

    Code:
    user="foo"
     host="bar@barfoo"
     r_dir="/home/foo/test"
     
     files = exec "ssh #{user}@#{host} ls #{r_dir}"

    This prints to STDOUT the contents of 'r_dir' - I'd like to put this into a array so I could iterate over the actual files that are in 'r_dir.'

    Do I have to use the I/O module?

  2. #2
    SitePoint Guru silver trophy Luke Redpath's Avatar
    Join Date
    Mar 2003
    Location
    London
    Posts
    794
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I'm not sure how to capture the results of exec, however there is probably a better way of sshing into a server and geting a list of a directory and I'd imagine you'll find net/ssh is the answer. Look here:

    http://net-ssh.rubyforge.org/chapter-4.html

  3. #3
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Unlike php, exec doesn't return. Use `` (backquotes) to run a subshell and capture output.

  4. #4
    SitePoint Member
    Join Date
    Jan 2003
    Posts
    15
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Backticks Worked - What About Getting the Shell Output, Though

    I played around with Net-SSH last week, I think it's a bit too much with what I want to do. Basically, I just need to log in to some remote machines and scp the files to a local machine.

    Code:
    files = `ssh #{user}@#{host} ls {r_dir}
    So that line pushes what I need into something I can iterate over.

    Code:
    files.each { | file |
           # remove the trailing new line
           file.chomp!
         
           # issue scp commands
           `scp #{user}@#{host}:#{r_dir}/#{file} #{l_dir}`
         }
    I'm have another quandry now though. How in the heck do I capture the output from that shell command to make sure the SCP actually went through? I saw this link about IO and was thinking that this would be the way to control for that - not sure though.

  5. #5
    SitePoint Guru silver trophy Luke Redpath's Avatar
    Join Date
    Mar 2003
    Location
    London
    Posts
    794
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by bivouac
    How in the heck do I capture the output from that shell command to make sure the SCP actually went through?
    Again, I think you are pushing against what you can do with the backtick operator/exec. Perhaps you should revisit net/ssh and if you can accomplish what you want that way - at least then you have the advantage of a full API and the ability to capture errors/exceptions as usual.

  6. #6
    SitePoint Wizard stereofrog's Avatar
    Join Date
    Apr 2004
    Location
    germany
    Posts
    4,324
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by bivouac
    IHow in the heck do I capture the output from that shell command to make sure the SCP actually went through?
    You should be able to check $? (command return code)

    Code:
    out = `command`
    if $? != 0 
       something went wrong

  7. #7
    SitePoint Zealot
    Join Date
    Nov 2004
    Location
    Yakima WA.
    Posts
    100
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    There is another easier way to drive shell commands from ruby and capture sdout, sterr and send stdin. My favorite is a gem called session:

    $ sudo gem install session

    Then its really easy to drive a shell in a subprocess. here's an example that will make a bash shell in ruby with prompts and everything:

    Code:
    #!/usr/bin/env ruby
    require 'tempfile'
    require 'readline'
    include Readline
    
    require 'rubygems'
    require 'session'
    
    shell = Session::Shell.new
    
    require 'tempfile'
    require 'readline'
    include Readline
    
    n = 0
    loop do
      command = readline("#{ n }: SHELL > ", true) 
      if command =~ /^\s*\!*history\!*\s*$/
        open('shell.history','w'){|f| f.puts shell.history}
        next
      end
      exit if command =~ /^\s*(?:exit|quit)\s*$/io
    
      out, err = shell.execute command
      out ||= ''
      err ||= ''
      printf "STDOUT:\n%s\nSTDERR:\n%s\n", out.gsub(%r/^/,"\t"), err.gsub(%r/^/,"\t")
      n += 1
    end
    Here is a little simpler example of just sending an ls command and capturing stout and sterr:

    Code:
    require 'tempfile'
    require 'rubygems'
    require 'session'
    
    shell = Session::Shell.new :history => false
    
    shell.execute('ls -ltar') do |out, err|
      if out
        puts "OUT:\n#{ out }"
      elsif err
        puts "ERR:\n#{ err }"
      end
    end
    puts shell.history
    Hopefully that help some. But Net::SSH is a great tool to drive ssh commands. And Net::SFTP might be worth l;ooking at too if you are trying to copy files from a remote server securely.

    Cheers

    -Ezra

  8. #8
    SitePoint Member
    Join Date
    Jan 2003
    Posts
    15
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Luke, the more I think about it the more I think you're right.

    Double drat.

    Was trying to accomplish this in an easy way and Net::SSH with it's channels and sessions seems confusing to me. I guess I'll need to master the module and see how it can fit into my script. But you're right - I can't reasonably tell with the backtick what's happening. With the Net::SSH module, I can monitor what's going on and then react appropriately.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •