Giter Site home page Giter Site logo

sshoogr's Introduction

sshoogr

GitHub Workflow Status ASL2 Licensed Latest Version

Overview

The sshoogr (pronounced [ʃʊgə]) is a Groovy-based DSL library for working with remote servers through SSH. The DSL allows:

  • connecting,
  • executing remote commands,
  • copying files and directories,
  • creating tunnels in a simple and concise way.

The library was jointly developed by Aestas/IT (http://aestasit.com) and NetCompany A/S (http://www.netcompany.com/) to support the quickly growing company's operations and hosting department.

Installing sshoogr with SDKMAN!

The simplest way to use sshoogr from the command line is by using SDKMAN!.

If SDKMAN is not yet installed, open a terminal and enter the following:

$ curl -s get.sdkman.io | bash

Follow the instructions presented in the terminal, then enter the following command:

$ sdk install sshoogr

This will install the sshoogr and make it available on your path.

Using sshoogr in Groovy scripts

The easiest way to use sshoogr in a Groovy script is by importing the dependency using Grape.

@Grab('com.aestasit.infrastructure.sshoogr:sshoogr:0.9.28')
import static com.aestasit.infrastructure.ssh.DefaultSsh.*

The entry point for using the DSL is the remoteSession method, which accepts an SSH URL and a closure with Groovy or DSL code:

remoteSession('user2:654321@localhost:2222') {
  exec 'rm -rf /tmp/*'
  exec 'touch /var/lock/my.pid'
  remoteFile('/var/my.conf').text = "enabled=true"
}

For more use cases, please refer to the following sections or to the examples folder in this repository.

Remote connections

The remoteSession method accepts an SSH URL and a closure, for example:

remoteSession("user:password@localhost:22") {
  //...
}

Inside the closure you can execute remote commands, access remote file content, upload and download files, create tunnels.

If your connection settings were set with the help of default configuration (see "Configuration options" section), then you can omit the URL parameter:

remoteSession {
  //...
}

Furthermore, it is possible to override the default values in each session by directly assigning host, username, password and port properties:

remoteSession {

  host = 'localhost'
  username = 'user2'
  password = '654321'
  port = 2222

  //...

}

The SSH's URL can be also assigned from withing the remote session declaration, like so:

remoteSession {

  url = 'user2:654321@localhost:2222'

  //...

}

The actual connection to the remote host will be executed upon the first command or file access, and, naturally, the connection will be automatically closed after the code block terminates.

You can explicitly call connect or disconnect methods to control this behavior:

remoteSession {

  // explicitly call connect
  connect()

  // do some stuff ...

  // explicitly disconnect
  disconnect()

  // explicitly connect again
  connect()

  //...

}

In the next section, we will see how to execute remote commands.

Executing commands

The simplest way to execute a command within a remote session is by using the exec method that just takes a command string:

remoteSession {
  exec 'ls -la'
}

You can also pass a list of commands in an array:

exec([
  'ls -la',
  'date'
])

The exec behavior can also be controlled with additional named parameters given to the method. For example, in order to hide commands output, you can use the following syntax:

exec(command: 'ls –la', showOutput: false)

The additional Parameter names are specified in the "Configuration options" section for the execOptions. They can all be used to override default settings for specific commands.

In the same way, you can also define common parameters for a block of commands passed as an array:

exec(showOutput: false, command: [
  'ls -la',
  'date'
])

Also you can get access to command output, exit code and exception thrown during command execution. This can be useful for implementing logic based on a result returned by the remote command and/or parsing of the output. For example,

def result = exec(command: '/usr/bin/mycmd', failOnError: false, showOutput: false)
if (result.exitStatus == 1) {
  result.output.eachLine { line ->
    if (line.contains('WARNING')) {
      throw new RuntimeException("Warning!!!")
    }
  }
}

Two additional methods that you can use around your commands are prefix and suffix. They are similar to using the prefix and suffix options in execOptions or named parameters to exec method.

prefix("sudo") {
  exec 'ls -la'
  exec 'df -h'
}

And with suffix:

suffix(">> output.log") {
  exec 'ls -la'
  exec 'df -h'
  exec 'date'
  exec 'facter'
}

File uploading/downloading

The simplest way to modify a remote text file content is by using remoteFile method, which returns a remote file object instance, and assign some string to the text property:

remoteFile('/etc/yum.repos.d/puppet.repo').text = '''
  [puppet]
  name=Puppet Labs Packages
  baseurl=http://yum.puppetlabs.com/el/$releasever/products/$basearch/
  enabled=0
  gpgcheck=0
'''

Each line of the input string will be trimmed before it's copied to the remote file. For text file downloading you can just read the text property:

println remoteFile('/etc/yum.repos.d/puppet.repo').text

Uploading of a single file can be done in the following way:

scp "$buildDir/test.file", '/tmp/test.file'

This method only works for file uploading (from local environment to remote). You can also write the example above in a more verbose form with the help of closures:

scp {
  from { localFile "$buildDir/test.file" }
  into { remoteFile '/tmp/test.file' }
}

A whole directory can be uploaded by using the remoteDir and localDir methods of scp.

scp {
  from { localDir "$buildDir/application" }
  into { remoteDir '/var/bea/domain/application' }
}

In similar fashion, you can download directories and files:

scp {
  from { remoteDir '/etc/nginx' }
  into { localDir "$buildDir/nginx" }
}

You can also copy multiple sources into multiple targets:

scp {
  from {
    localDir "$buildDir/doc"
    localFile "$buildDir/readme.txt"
    localFile "$buildDir/license/license.txt"
  }
  into {
    remoteDir '/var/server/application'
    remoteDir '/repo/company/application'
  }
}

During any upload/download operation, local and remote directories will be created automatically.

Tunneling

If inside your build script you need to get access to a remote server that is not visible directly from the local machine, then you can create a tunnel to that server by using the tunnel method:

tunnel('1.2.3.4', 8080) { int localPort ->
  //...
}

All code executed within the closure passed to the tunnel method will have access to a server tunnel running on localhost and randomly selected localPort, which is passed as a parameter to the closure. Inside that tunnel code you can, for example, deploy a web application or send some HTTP command to remote server:

tunnel('1.2.3.4', 8080) { int localPort ->
  def result = new URL("http://localhost:${localPort}/flushCache").text
  if (result == 'OK') {
    println "Cache is flushed!"
  } else {
    throw new RuntimeException(result)
  }
}

The tunnel will be closed upon closure completion. Also, you can define a local port yourself in the following way:

tunnel(7070, '1.2.3.4', 8080) {
  def result = new URL("http://localhost:7070/flushCache").text
  //...
}

Configuration options

The following list gives an overview of the available configuration options:

  • defaultHost, defaultUser, defaultPassword, defaultPort (defaults to 22) - Default host, user name, password or port to use in remote connection in case they are not specified in some other way (through url, host, port, user or password properties inside the remoteSession method).
  • defaultKeyFile - Default key file to use in remote connection in case it is not specified through the keyFile property inside the remoteSession method.
  • failOnError (defaults to true) - If set to true, failed remote commands and file operations will throw an exception.
  • verbose (defaults to false) - If set to true, the library produces more debug output.

The sshOptions may also contain a nested execOptions structure, which defines remote command execution (see "Executing commands" section) options. It has the following properties:

  • showOutput (defaults to true) - If set to true, remote command output is printed.
  • showCommand (defaults to true) - If set to true, remote command is printed.
  • hideSecrets (defaults to true) - If set to true, secret Strings contained in ExecOptions.secrets will be redacted from output and replaced by ********.
  • secrets (defaults to [ ]) - a list of secret Strings to be redacted from output
  • maxWait (defaults to 0) - Number of milliseconds to wait for command to finish. If it is set to 0, then library will wait forever.
  • succeedOnExitStatus (defaults to 0) - Exit code that indicates commands success. If command returns different exit code, then build will fail.
  • failOnError (defaults to true) - If set to true, failed remote commands will fail the build.
  • verbose (defaults to false) - If set to true, library produces more debug output.
  • prefix - String to prepend to each executed command, for example, "sudo".
  • suffix - String to append to each executed command, for example, ">> output.log".

There is also a nested scpOptions structure, which defines remote file copying options (see "File uploading/downloading" section). It has the following properties:

  • failOnError (defaults to true) - If set to true, failed file operations will fail the build.
  • showProgress (defaults to false) - If set to true, library shows additional information regarding file upload/download progress.
  • verbose (defaults to false) - If set to true, library produces more debug output.

Advanced usage

Creating a SshDslEngine instance

If you need to embed sshoogr into your own DSL or another library you may need to use internal classes instead of default static methods. The main library's classes are SshDslEngine and SshOptions, which need to be imported before the library can be used:

import com.aestasit.infrastructure.ssh.dsl.SshDslEngine
import com.aestasit.infrastructure.ssh.SshOptions

To create a simple instance of the engine with the default options you can just use the following instruction:

def engine = new SshDslEngine(new SshOptions())

The engine instance gives access to the remoteSession method.

Populating SshOptions

A more verbose example of creating a SshOptions object can be found below:

import com.aestasit.infrastructure.ssh.log.SysOutLogger

//...

options = new SshOptions()
options.with {

  logger = new SysOutLogger()

  defaultHost = '127.0.0.1'
  defaultUser = 'user1'
  defaultPassword = '123456'
  defaultPort = 2233

  reuseConnection = true
  trustUnknownHosts = true

  execOptions.with {
    showOutput = true
    failOnError = false
    hideSecrets = true
    secrets = ['secret1']
    succeedOnExitStatus = 0
    maxWait = 30000
  }

  scpOptions.with {
    verbose = true
    showProgress = true
  }

}

sshoogr's People

Contributors

aadamovich avatar aalmiray avatar antonmry avatar bitdeli-chef avatar jasonkdarby avatar keyvanakbary avatar lfiandesio avatar luciano-fiandesio avatar marc0der avatar raymyers avatar stigkj avatar tomverin avatar valdisrigdon avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sshoogr's Issues

Publish bits to Maven Central

It would be great library would be in Maven Central. If you are using a different repository, it should be noted in readme file so people can easily @grab it

multi threading issue

Hi, I have a groovy program to upload text files to lots of different servers (200-1600 VMs) Using Gpars I am able to spawn many ssh/scp threads to different hosts.
build.gradle dependencies

compile 'org.codehaus.groovy:groovy-all:1.8.4'
compile "com.aestasit.infrastructure.sshoogr:sshoogr:0.9.15"
compile "com.jcraft:jsch:0.1.51"
compile group: 'org.codehaus.gpars', name: 'gpars', version: '1.0.0'

This works in serial with a thread pool of 1, but when I try 10 or 100 concurrent, sshoogr or jsch locks up:

For example where agentList is a ArrayList of 200 Agents (objects with hostname, os type, etc)
and toServer is my target server to direct the agents to (hostname).

public void test()
{
        Thread thread = Thread.start()
        {
                try
                {
                    GParsPool.withPool(10)
                        {
                            agentList.eachParallel
                                {
                                    agent ->
                                    agent.setServerHost(toServer)
                                }
                        }
                }
                catch (Exception e)
                {
                    e.printStackTrace()
                }
            }

        thread.join()
}

and agent.setServerHost(toServer) simply writes a property file and scp it to the host

        println "Copying agent.properties to $hostname"
    remoteSession("root:perfwire@$hostname:22")
    {
        scp properties.absolutePath, "/var/tmp/agent.properties"
    }

Running this you see my debug output copying agent properties to 10 different hosts, but the sshoogr output

Connecting to the same host 10 times.
If I run it a few times it works and copies a bunch but hangs eventually.
All the hosts are up and I've done this from bash (ssh'ing to all hosts to copy a file).

loaded agent list size: 200
Copying agent.properties to dhcp-10-248-8-201.ddns.perf.lab.test.com
Copying agent.properties to dhcp-10-248-8-137.ddns.perf.lab.test.com
Copying agent.properties to dhcp-10-248-8-100.ddns.perf.lab.test.com
Copying agent.properties to dhcp-10-248-8-87.ddns.perf.lab.test.com
Copying agent.properties to dhcp-10-248-8-150.ddns.perf.lab.test.com
Copying agent.properties to dhcp-10-248-8-125.ddns.perf.lab.test.com
Copying agent.properties to dhcp-10-248-8-175.ddns.perf.lab.test.com
Copying agent.properties to dhcp-10-248-8-50.ddns.perf.lab.test.com
Copying agent.properties to dhcp-10-248-8-75.ddns.perf.lab.test.com
Copying agent.properties to dhcp-10-248-8-226.ddns.perf.lab.test.com
> Connecting to dhcp-10-248-8-201.ddns.perf.lab.test.com
> Connecting to dhcp-10-248-8-201.ddns.perf.lab.test.com
> Connecting to dhcp-10-248-8-201.ddns.perf.lab.test.com
> Connecting to dhcp-10-248-8-201.ddns.perf.lab.test.com
> Connecting to dhcp-10-248-8-201.ddns.perf.lab.test.com
> Connecting to dhcp-10-248-8-201.ddns.perf.lab.test.com
> Connecting to dhcp-10-248-8-201.ddns.perf.lab.test.com
> Connecting to dhcp-10-248-8-201.ddns.perf.lab.test.com
> Connecting to dhcp-10-248-8-201.ddns.perf.lab.test.com
> Connecting to dhcp-10-248-8-201.ddns.perf.lab.test.com
<hang>

One of many threads looks like this. All stuck in socketRead and RUNNABLE.

"ForkJoinPool-1-worker-9" daemon prio=6 tid=0x0000000008a17000 nid=0x3bc runnable [0x0000000009918000]
   java.lang.Thread.State: RUNNABLE
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:129)
    at java.net.SocketInputStream.read(SocketInputStream.java:182)
    at com.jcraft.jsch.IO.getByte(IO.java:73)
    at com.jcraft.jsch.Session.connect(Session.java:263)
    at com.jcraft.jsch.Session.connect(Session.java:183)
    at com.jcraft.jsch.Session$connect.call(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
    at com.aestasit.ssh.dsl.SessionDelegate.connect(SessionDelegate.groovy:94)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1085)
    at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:730)
    at org.codehaus.groovy.runtime.metaclass.OwnedMetaClass.invokeMethod(OwnedMetaClass.java:97)
    at com.aestasit.ssh.dsl.ScpMethods.invokeMethod(ScpMethods.groovy)
    at org.codehaus.groovy.runtime.callsite.PogoInterceptableSite.call(PogoInterceptableSite.java:45)
    at org.codehaus.groovy.runtime.callsite.PogoInterceptableSite.callCurrent(PogoInterceptableSite.java:55)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:137)
    at com.aestasit.ssh.dsl.ScpMethods.sftpChannel(ScpMethods.groovy:255)
    at com.aestasit.ssh.dsl.ScpMethods.this$2$sftpChannel(ScpMethods.groovy)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod.invoke(MixinInstanceMetaMethod.java:53)
    at groovy.lang.MetaClassImpl.invokeMissingMethod(MetaClassImpl.java:817)
    at groovy.lang.MetaClassImpl.invokePropertyOrMissing(MetaClassImpl.java:1134)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1087)
    at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:730)
    at org.codehaus.groovy.runtime.metaclass.OwnedMetaClass.invokeMethod(OwnedMetaClass.java:97)
    at com.aestasit.ssh.dsl.ScpMethods.invokeMethod(ScpMethods.groovy)
    at org.codehaus.groovy.runtime.callsite.PogoInterceptableSite.call(PogoInterceptableSite.java:45)
    at org.codehaus.groovy.runtime.callsite.PogoInterceptableSite.callCurrent(PogoInterceptableSite.java:55)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
    at com.aestasit.ssh.dsl.ScpMethods.scp(ScpMethods.groovy:44)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod.invoke(MixinInstanceMetaMethod.java:53)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1085)
    at groovy.lang.ExpandoMetaClass.invokeMethod(ExpandoMetaClass.java:1110)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:730)
    at org.codehaus.groovy.runtime.metaclass.OwnedMetaClass.invokeMethod(OwnedMetaClass.java:97)
    at com.aestasit.ssh.dsl.ScpMethods.invokeMethod(ScpMethods.groovy)
    at org.codehaus.groovy.runtime.callsite.PogoInterceptableSite.call(PogoInterceptableSite.java:45)
    at org.codehaus.groovy.runtime.callsite.PogoInterceptableSite.callCurrent(PogoInterceptableSite.java:55)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145)
    at com.aestasit.ssh.dsl.ScpMethods.scp(ScpMethods.groovy:40)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at org.codehaus.groovy.runtime.metaclass.MixinInstanceMetaMethod.invoke(MixinInstanceMetaMethod.java:53)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:361)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:145)
    at com.tripwire.lab.Agent$_copyAgentProperties_closure4.doCall(Agent.groovy:84)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at com.aestasit.ssh.dsl.SshDslEngine.executeSession(SshDslEngine.groovy:70)
    at com.aestasit.ssh.dsl.SshDslEngine.this$2$executeSession(SshDslEngine.groovy)
    at com.aestasit.ssh.dsl.SshDslEngine$this$2$executeSession$5.callCurrent(Unknown Source)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:149)
    at com.aestasit.ssh.dsl.SshDslEngine.remoteSession(SshDslEngine.groovy:54)
    at com.aestasit.ssh.dsl.SshDslEngine$remoteSession$2.callCurrent(Unknown Source)
    at com.aestasit.ssh.dsl.SshDslEngine.remoteSession(SshDslEngine.groovy:50)
    at com.aestasit.ssh.dsl.SshDslEngine$remoteSession$0.call(Unknown Source)
    at com.aestasit.ssh.DefaultSsh.remoteSession(DefaultSsh.groovy:56)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite$StaticMetaMethodSiteNoUnwrap.invoke(StaticMetaMethodSite.java:130)
    at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.callStatic(StaticMetaMethodSite.java:99)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:53)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:157)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:169)
    at com.tripwire.lab.Agent.copyAgentProperties(Agent.groovy:81)
    at com.tripwire.lab.Agent$copyAgentProperties$10.callCurrent(Unknown Source)
    at com.tripwire.lab.Agent.setServerHost(Agent.groovy:70)
    at com.tripwire.lab.Agent$setServerHost$4.call(Unknown Source)
    at com.tripwire.lab.TEAgentManager$_redirect_closure1_closure3_closure4.doCall(TEAgentManager.groovy:42)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at groovyx.gpars.pa.GParsPoolUtilHelper$_eachParallelPA_closure8.doCall(GParsPoolUtilHelper.groovy:190)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
    at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
    at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:272)
    at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:909)
    at groovy.lang.Closure.call(Closure.java:411)
    at org.codehaus.groovy.runtime.ConvertedClosure.invokeCustom(ConvertedClosure.java:51)
    at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:81)
    at $Proxy5.op(Unknown Source)
    at groovyx.gpars.extra166y.AbstractParallelAnyArray$OUPap.leafApply(AbstractParallelAnyArray.java:639)
    at groovyx.gpars.extra166y.PAS$FJOApply.atLeaf(PAS.java:147)
    at groovyx.gpars.extra166y.PAS$FJBase.internalCompute(PAS.java:118)
    at groovyx.gpars.extra166y.PAS$FJBase.compute(PAS.java:106)
    at jsr166y.RecursiveAction.exec(RecursiveAction.java:148)
    at jsr166y.ForkJoinTask.doExec(ForkJoinTask.java:305)
    at jsr166y.ForkJoinWorkerThread.execTask(ForkJoinWorkerThread.java:575)
    at jsr166y.ForkJoinPool.scan(ForkJoinPool.java:733)
    at jsr166y.ForkJoinPool.work(ForkJoinPool.java:617)
    at jsr166y.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:369)

Validate named arguments

In particular, it took me some time that I have typed commands rather than command in the exec arg list.

Please provide a way to seed SSH configuration and host keys

Hi,

Please provide a way to seed SSH configuration and tell Jsch about host keys. Currently, the following Jsch options are hardcoded[1]:

  config.put("StrictHostKeyChecking", "no")
  config.put("HashKnownHosts", "yes")
  config.put("PreferredAuthentications", "publickey,keyboard-interactive,password")

We would like to be able to enable StrictHostKeyChecking and provide the public key of the target host to Jsch.

Thank you in advance,

[1]https://github.com/aestasit/sshoogr/blob/master/src/main/groovy/com/aestasit/ssh/dsl/SshDslEngine.groovy#L40

Propagation of options is broken

Hi, is there any further documentation explaining how to set ScpOptions without created a separate engine? I have tried various permutations on (I am new to Groovy, but I did do a bit of research):

remoteSession {
  host = args[0]
  username = args[1]


  scpOptions({
    showProgress = false
    verbose = false
  })
  scp "/tmp/foo.zip", '/tmp'
}

however I am still seeing the progress, and when foo.zip is large it is extremely verbose.

Also, the docs say showProgress default is false, which I believe is wrong.

Allow exec.command to take a GString (or things that can be coerced to a String)

It would be nice to support GStrings in places where Strings are appropriate. For example, this fails:

def site = "www.google.com"
def result = exec(command: "host $site", showOutput: false)

I have to add a .toString() to the parameter passed to command

I'd be willing to implement this if you'd accept a Pull Request, but would need a few pointers on where to get started.

Kerberos prompt

I'm not sure if this is the right forum for this, but I did not see any other means of reaching out to the developers of this project.

Recently, I've attempted to use groovy-ssh-dsl to connect to a remote server. I've set up the script to use a particular default host, default user, and default password. However, when I attempt to run the script, it returns a Kerberos prompt

$ groovy SshExample.groovy

07:37:03.799 [main] INFO  com.aestasit.ssh.log - >>> Connecting to sptqa-app2.xyz.aert.com
Kerberos username [STAGR005]:

The prompt shows my workstation username. Is there a way to exclude this sort of behavior (i.e., not to use my local workstation username with Kerberos)? I just want it to ssh into the remote box using the default information I've provided within the script

small typo in README.md

there is a small typo in README.md
I think the code:
import static com.aestasit.ssh.DefaulSsh.*
should be
import static com.aestasit.ssh.DefaultSsh.*

Groovy script hang on exit if exception thrown within remoteSession

If you use outer try block for remoteSession and generate exception from within remoteSession it cause the script hang on exit.
Here is code example:

@Grab(group='com.aestasit.infrastructure.sshoogr', module='sshoogr', version='0.9.16')

import static com.aestasit.ssh.DefaultSsh.*
import java.util.concurrent.TimeoutException

setDefaultKeyFile(new File(System.getenv("HOME")+"/.ssh/id_rsa"))
def user = System.getenv("USER")

try {
    remoteSession ("${user}@localhost:22"){
        exec "echo Hello world!"
        throw new TimeoutException("Bang!")
    }
} catch (e) {
    println "Warning: ${e.message}"
}
println "Good bye"

The output looks like follows:

>>> Connecting to localhost
> echo Hello world!
Hello world!
Warning: Bang!
Good bye

SCP upload should check for absolute path existence

Hi guys!

In com.aestasit.ssh.dsl.ScpMethods#upload (ScpMethods.groovy:78) the destination directory is resolved as relative path (using org.apache.commons.io.FilenameUtils#getPath).
In my case this leads to JSCH Error "2: No such file" when supplying an absolute path.

Suggestion: use "getFullPath(dstFile)" to work with the absolute path! Then one should be on the safe side.

Best regards,
Klaus L.

Sudo prompt

Hi guys,
probably not so much a code issue, but how do you handle sudo password prompts with sshoogr? I tried fumbling around with sudo -S -p options and then trying to get the password in via stdin, but to no avail. Have you got any working examples? Thanks

Add better logging control

Logging is too verbose (especially for scp). We need to rethink the logging overall and make it more friendly and configurable (both in Groovy and Gradle)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.