Showing posts with label script. Show all posts
Showing posts with label script. Show all posts

Wednesday, December 8, 2010

More Groovy Weirdness

I love Groovy.  There is no telling how much time it has saved me in scripting simple tasks.  I do stumble over groovy sometimes though, and it seems it mostly relates to scoping rules.

I am the first to admit, I do not write scripts very 'Groovily'.  It looks more like Java that uses some nice closures when convenient (but, boy are those /really/ convenient).  So I am sure that if I stuck to a more Groove like style I would not run into these problems but today I wrote a simple script.  I put a bunch of variables at the top of the script and ran it and --- Whoops I tripped over a groovy.lang.MissingPropertyException: No such property:  for class exception.

Turns out, in a Groovy script, variables that are not defined within methods /cannot/ have either an explicit type or a def.  This is easy to fix, of course.  Just let Groovy handle the duck typing or turn the script into a class but still, a little surprising.

Running remote command over ssh with Groovy

This post is for those who are searching for how to run a remote command over ssh through a groovy script.  Hopefully it will save someone a lot of searching....spoiler alert:  There does not seem to be a clean way to do this.

It is trivial to run a command on a remote system over ssh, especially if you have keys set up between the machines that are communicating.  Just
ssh user@remote_server command_you_would_like_to_run'.

Things get surprisingly complicated when you want to script this kind of interaction.  I believe that this is because most ssh implementations use tty and it is made difficult by design to use in a scripted environment (and rightly so, since it is a security risk).

I simply wanted to connect to a remote server with groovy and list the files in a known directory.  I was hoping that I could do this with groovy's .execute().text since I did not need to send passwords or anything else because I have keys set up between the machines.  No dice.  I tried the array version of .execute too and still no joy.  What I ended up having to do is to create a simple bash script:

 #!/bin/bash
 ssh user@remote_server 'ls /directory_I_am_interested_in'


which I called ls_script so my groovy line became:


 def listOfFiles = "ls_script".execute().text


I did not like calling outside of the original script but it is quick and it works.

If it makes sense for the overall job at hand, there is a wonderful python library called pexpect .  Somehow this great little library very cleanly bypasses the tty issues I mentioned earlier.

Here is a simple use case of pexpect:


 spawnString = 'ssh ' + thisLogin + '@' + thisIP + ' -p ' + thisPort
 foo = pexpect.spawn(spawnString)
 ssh_newkey = 'Are you sure you want to continue connecting'
 i = foo.expect([ssh_newkey, 'password'])
        if i == 0:
            foo.sendline('yes')
            i = foo.expect([ssh_newkey, 'password'])
        if i == 1:
            foo.sendline(thisPassword)
 foo.sendline(' ')
 data = foo.readline()


Checkout the sourceforge page and http://www.noah.org/wiki/pexpect which I believe is the original creator's site with some nice documentation.