How to net-ssh sudo su in Ruby
Asked Answered
P

1

6

I'm trying to figure out how to a send chain of multiple net-ssh commands after a sudo su - #{su_user} in Ruby.

My current code is below, and hangs with the sudo su command, even after the send_data "#{password}\n".

Meanwhile, on the system, a manual execution of sudo su - admin2 does not require a password entry.

Any help would be appreciated!


require 'rubygems'  
require 'net/ssh'
host = 'hostA'

user = 'admin'
password = 'hostA_pwd'
su_user = 'Admin2'

Net::SSH.start(host, user, :password => password) do |ssh|

     ssh.open_channel do |channel|  
       channel.request_pty do |c, success|
         raise "could not request pty" unless success

         channel.exec "pwd; whoami; sudo su - #{su_user} ; pwd ; whoami"
         channel.on_data do |c_, data|
           if data =~ /\[sudo\]/ || data =~ /Password/i
             channel.send_data "#{password}\n"
           else       
             result << data
           end
         end
         puts result
       end
     end
     ssh.loop
  end
Porcia answered 4/12, 2012 at 14:11 Comment(1)
You are aware that you can't chain commands like that after the sudo command? The last pwd; whoami won't be executed until after the sudo command shell returns. Did you take this into account?Admissible
C
3

sudo supports the -c option, which passes a command to the sub-shell. Here are some of the sudo flags that might be useful to you:

-c, --command=COMMAND
      pass a single COMMAND to the shell with -c

--session-command=COMMAND
      pass a single COMMAND to the shell with -c and do not create a new session

-m, --preserve-environment
      do not reset environment variables

-s, --shell=SHELL
      run SHELL if /etc/shells allows it

So, using something like sudo su someuser -c 'ls;date', you'll execute the commands ls and date as someuser. Give it a try at the command-line on that host to get a feel for what you can do, then apply it to your SSH session.

See man sudo for more information.

Also, just as a coding tip, you can reduce:

if data =~ /\[sudo\]/ || data =~ /Password/i

to:

if (data[/\[sudo\]|Password/i])
Citriculture answered 4/12, 2012 at 14:58 Comment(2)
thanks for the reply, I modified the line in code to include the -c option as Tin Man recommended. Thanks. <br /> channel.exec "pwd; whoami; sudo -u #{su_user} sh -c 'whoami ; cd /tmp ; pwd; ls'"Porcia
This was a great tip passing in -c 'command' under the sudo su someuser works well. That was a great tip.Odey

© 2022 - 2024 — McMap. All rights reserved.