Long title...
Anyway, recently need to use groovy to ssh tunnel to a remote host to execute commands.
Here is a rather convoluted and contrived example of how to do it.
Create x.groovy somewhere.
First we import jsch:
import com.jcraft.jsch.JSch import com.jcraft.jsch.Session import com.jcraft.jsch.UserInfo import com.jcraft.jsch.Channel import com.jcraft.jsch.ChannelExec
And properties..
import java.util.Properties
Now we create some variables defining the ssh firewall server, localhost and the target host:
def sshHost = '192.168.1.1' def sshUser = 'ssh_user' def sshPass = 'ssh_password' def sshPort = 22 def localHost = '127.0.0.1' def targetHost = '172.16.1.1' def targetUser = 'target_user' def targetPass = 'target_password' def targetPort = 22
We start first by setting up the properties.
You don't strictly need properties as a HashMap would do.
println "Opening connection to ${sshUser}@${sshHost}:${sshPort}" Properties config = new Properties() config.put("StrictHostKeyChecking", "no") JSch jsch = new JSch()
Now we get our session to the firewall:
Session sshSession = jsch.getSession(sshUser, sshHost, sshPort) sshSession.setPassword(sshPass) sshSession.setConfig(config) sshSession.connect() println "Connected"
Now we get a free port and forward localhost to the target machine:
println "Forwarding connection to ${targetHost}:${targetPort}" def assignedPort = sshSession.setPortForwardingL(0, targetHost, targetPort) println "Got port $assignedPort"
Now we have two choices. Use AntBuilder with the sshexec call, or do raw InputStream reads:
1 - Use AntBuilder:
def result = '' def ant = new AntBuilder() // This bit is to stop ant hijacking stdout. logger = ant.project.buildListeners.find { it instanceof org.apache.tools.ant.DefaultLogger } logger.messageOutputLevel = 0 logger.emacsMode = true // Ok. Do it... ant.sshexec( host: localHost, port: assignedPort, trust: true, username: targetUser, password: targetPass, command: '/bin/hostname', outputproperty: 'result', verbose: false ) // And show the result println ant.project.properties.'result'
2 - Use raw InputStream handling:
Session targetSession = jsch.getSession(targetUser, localHost, assignedPort) targetSession.setPassword(targetPass) targetSession.setConfig(config) targetSession.connect() println "Connected" // Could use "shell" Channel channel = targetSession.openChannel("exec") // Let's just get the hostname ((ChannelExec)channel).setCommand("/bin/hostname") // Spew errors to console ((ChannelExec)channel).setErrStream(System.err) // We're not sending anything channel.setInputStream(null) // Get the input stream InputStream is = channel.getInputStream() // Connect channel.connect() // This could be written better and groovier... byte[] tmp = new byte[1024] // Uh oh. We really need a better way out of the loop... :-( while (true) { // But it's just an example... :-) while (is.available() > 0) { int i = is.read(tmp, 0, 1024) if (i<0) break System.out.print(new String(tmp, 0, i)) } if (channel.isClosed()) { // All done. System.out.println("exit-status: " + channel.getExitStatus()) break } // Ugly: You might want to change this try{Thread.sleep(1000);}catch(Exception ee){} } // Close channel and session channel.disconnect() targetSession.disconnect()
And finally disconnect:
sshSession.disconnect()
Now how do you run it? You have to tell groovy where the jars are...
groovy -cp /path/to/jsch-0.1.46.jar:/path/to/ant-jsch.jar x.groovy
No comments:
Post a Comment