Publicidad

Groovy on the shell

2 de Jun de 2017
Publicidad

Más contenido relacionado

Publicidad
Publicidad

Groovy on the shell

  1. Groovy on the shell_ Alexander (Sascha) Klein <alexander.klein@codecentric.de>   1
  2. Why ?   2
  3. Groovy is cool   3
  4. Because I can   4
  5. To do complex stuff   5
  6. Testing your scripts   6
  7. If you know Groovy better than Bash   7
  8. About me Alexander Klein Branchmanager codecentric AG Curiestr. 2 70563 Stuttgart, Germany +49 (0) 172 529 40 20 alexander.klein@codecentric.de www.codecentric.de blog.codecentric.de @saschaklein   8
  9. Executing Groovy scripts $ groovy Test.groovy   9
  10. She-Bang Comment (#!) #!/usr/local/bin/groovy   10
  11. Using the default environment Defining the classpath Using system variables Defining system variables #!/usr/bin/env groovy #!/usr/bin/env groovy -cp myjar.jar #!/usr/bin/env groovy -cp ${HOME}/bin #!/usr/bin/env VAR1=value1 VAR2=value2 groovy   11
  12. But Does not work on Linux Alternative script for /usr/bin/env Without defining system variables #!/bin/bash ARGS=( $1 ) # separate $1 into multiple space-delimited arguments. shift # consume $1 PROG=`which ${ARGS[0]}` # find path for executable unset ARGS[0] # discard executable name ARGS+=( "$@" ) # remainder of arguments preserved "as-is". # iterate array and expand variables declare -a PARAMS for i in "${ARGS[@]}" do PARAMS=("${PARAMS[@]}" "`eval "echo $i"`") done exec $PROG "${PARAMS[@]}" # execute the command   12
  13. 'Hacks' for the rescue #!/bin/bash //usr/bin/env /path/to/groovy "$0" $@; exit $? println "My groovy script" #!/bin/bash //usr/bin/true && export CLASSPATH=.... //usr/bin/true && export OPTS="-Dmy.opt1=foo -Dmy.opt2=bar" //usr/bin/true && export OPTS="$OPTS -Dmy.opt3=foobar" //path/to/groovy $OPTS "$0" $0; exit $? println System.env[my.opt1]   13
  14. 'Hacks' for the rescue #!/bin/bash REM=''' ' # bash stuff here export export CLASSPATH=.... export OPTS="-Dmy.opt1=foo -Dmy.opt2=bar" export OPTS="$OPTS -Dmy.opt3=foobar" /path/to/groovy $OPTS "$0" $@ exit $? ' ''' // groovy stuff here println "My groovy script"   14
  15. A solution for Windows @ECHO OFF REM = / REM dummy groovy statement in first line with an REM assignment to a dummy var called REM SET _JAVA_OPTIONS= SET CLASSPATH= C:pathtogroovy "%~dp0%~nx0" %* GOTO :EOF / // dummy groovy annotation to make groovy compiler // to ignore the first line @interface ECHO {} // groovy stuff here println "My groovy script"   15
  16. GroovyServ Faster Startup JVM process running in the background Scriptstart ~10-20 times faster   16
  17. Installation Windows GroovyServ is part of the Groovy Windows-Installer Linux Mac OS X Binary package curl -s "https://get.sdkman.io" | bash sdk install groovyserv brew install groovyserv $ cd /tmp $ unzip groovyserv-1.1.0-bin.zip $ groovyserv-1.1.0-bin/bin/setup.sh export PATH=/tmp/groovyserv-1.1.0/bin:$PATH   17
  18. Usage $ groovyclient MyScript.groovy #!/usr/bin/env groovyclient   18
  19. Writing Scripts   19
  20. Restrictions Classname == Filename to be found from other script   20
  21. Executing shell commands "mkdir foo".execute() ["mkdir", "my directory"].execute()   21
  22. Workingdir & Environment "ls".execute([], new File("/tmp")) "env".execute(["VAR1=Test", "VAR2=Something"], new File(".")) "env".execute([*:System.env, VAR1: 'Test'] .collect{ k,v -> "$k=$v" }, new File("."))   22
  23. Result access println "ls".execute().text println "cmd /c dir".execute().text "ls".execute().inputStream.eachLine { println it } "ls".execute().in.eachLine { println it } "myCommand".execute().err.eachLine { println it } def proc = new ProcessBuilder("myCommand") .redirectErrorStream(true).start() proc.in.eachLine { println it }   23
  24. Process control Process process = "mkdir foo".execute() process.waitFor() int exitValue = process.exitValue() if(!exitValue) { //do your error-handling } if(!"mkdir foo".execute().waitFor()) { //do your error-handling } "grep pattern".execute().waitForOrKill(1000) def process = "myLongRunningCommand".execute() ... process.destroy()   24
  25. Process output Process process = "myCommand".execute() def out = new StringBuffer() def err = new StringBuffer() process.waitForProcessOutput( out, err ) if( out.size() > 0 ) println out if( err.size() > 0 ) println err def p = "rm -f foo.tmp".execute([], tmpDir) p.consumeProcessOutput() // Prevent blocking by small buffer p.waitFor()   25
  26. Piping "less temp.sh".execute().pipeTo("grep Detected".execute()).text def proc1 = "less temp.sh".execute() def proc2 = "grep Detected".execute() proc1 | proc2 println proc2.text   26
  27. Wildcards "ls *.java".execute() // won't work "sh -c ls *.java".execute() // Shell resolves the wildcard   27
  28. Shell Helper I class Shell { final Map env = System.env File dir = new File('.') boolean redirectErrorStream = false long timeout = 5000 Shell env(Map env) { this.env.putAll(env); return this } Shell dir(File dir) { this.dir = dir; return this } Shell dir(String dir) { this.dir = new File(dir); return this } Shell redirectErrorStream(boolean redirectErrorStream = true) { this.redirectErrorStream = redirectErrorStream; return this } Shell timeout(int timeout = 5000) { this.timeout = timeout; return this }   28
  29. Shell Helper II Process execute(String command) { new ProcessBuilder(['sh', '-c', command]) .directory(dir) .redirectErrorStream(redirectErrorStream) .environment(env.collect{k,v -> "$k=$v"} as String[]) .start() } int call(String command, boolean consumeOutput = true) { Process proc = execute(command) if(consumeOutput) proc.consumeProcessOutput() if(timeout) proc.waitForOrKill(timeout) else proc.waitFor() return proc.exitValue() } def eachLine(String command, Closure action) { execute(command).in.eachLine(action) } }   29
  30. Shell Helper III def shell = new Shell() shell.call("mkdir /tmp/groovy") shell("echo 123 >> /tmp/groovy/test") shell.dir("/tmp/groovy").call("echo $HOME >> test2") shell.eachLine("ls ."){ println "- $it -" } shell.eachLine("cat test2"){ println "- $it -" }   30
  31. Helpfull stuff Accessing System-Variables Accessing System-Properties Get your PID println System.env.PWD println System.properties.'user.dir' import java.lang.management.* println ManagementFactory.runtimeMXBean.name.split('@').first()   31
  32. CliBuilder   32
  33. Parsing Commandline arguments DSL ontop of Apache Commons CLI !#/usr/bin/env groovy def cli = new CliBuilder(usage: 'MyScript') cli.with { v(longOpt: 'version', 'show version information') } def opt = cli.parse(args) if (!opt) System.exit(2) if (opt.v) { println "Version: 1.0.0" }   33
  34. A Sample usage: MyScript [options] [args] -?,--help usage information --config <arg> A script for tweaking the configuration -D <property=value> use value for given property -s,--source <path> Aliases for '-source' -source <path> Specify where to find the files -v,--version version information   34
  35. The code I #!/usr/bin/env groovy def cli = new CliBuilder(usage: 'MyScript [options] [args]') cli.with { source(args:1, argName: 'path', optionalArg: false, 'Specify where to find the files') _ (longOpt: 'config', args:1, argName: 'arg', optionalArg: false, 'A script for tweaking the configuration') s (longOpt: 'source', args:1, argName:'path', optionalArg: false, "Aliases for '-source'") '?' (longOpt: 'help', 'usage information') v (longOpt: 'version', 'version information') D (args: 2, valueSeparator: '=', argName: 'property=value', 'use value for given property') }   35
  36. The code II def opt = cli.parse(args) if (!opt) // usage already displayed by cli.parse() System.exit(2) if(opt.'?') cli.usage() else if (opt.v) println "Version: 1.0.0" else { if (opt.config) println "Configuration: $opt.config" if(opt.D) { println "Custom properties:" println opt.Ds.collate(2).collect{ it.join('=') }.join('n') } def home = System.properties.'user.dir' if (opt.s || opt.source) home = opt.s ?: opt.source println "Working on files:" opt.arguments().each println "$home/$it" }   36
  37. Questions? Alexander Klein Branchmanager codecentric AG Curiestr. 2 70563 Stuttgart, Germany +49 (0) 172 529 40 20 alexander.klein@codecentric.de www.codecentric.de blog.codecentric.de @saschaklein   37
  38. Dependency Management   38
  39. Grape Groovy Adaptable Packaging Engine Cachedirectory ~/.groovy/grape @Grab(group='org.springframework', module='spring-orm', version='3.2.5.RELEASE') import org.springframework.jdbc.core.JdbcTemplate @Grab('org.springframework:spring-orm:3.2.5.RELEASE') import org.springframework.jdbc.core.JdbcTemplate   39
  40. @Grab Annotation I Annotatable everywhere often seen at import statements group (String) Maven groupId or Ivy organization module (String) Maven artifactId or Ivy artifact version (String) literal '1.1-RC3' Ivy range '[1.0, 2,0]' → 1.0 or 2.0 '[2.1,)' → 2.1 or greater classifier (String) 'jdk15' optional   40
  41. Multiple Dependencies @Grapes([ @Grab(group='commons-primitives', module='commons-primitives', version='1.0'), @Grab(group='org.ccil.cowan.tagsoup', module='tagsoup', version='0.9.7') ]) class Example { ... }   41
  42. Repositories Configuration in ~/.groovy/grapeConfig.xml Grape cache → ~/.groovy/grapes Maven Local → ~/.m2/repository JCenter (includes Maven Central) IBiblio Java.net http://jcenter.bintray.com http://www.ibiblio.org http://download.java.net/maven/2 @GrabResolver(name='restlet', root='http://maven.restlet.org/') @Grab(group='org.restlet', module='org.restlet', version='1.1.6')   42
  43. Exclude transitive dependencies @Grab('net.sourceforge.htmlunit:htmlunit:2.8') @GrabExclude('xml-apis:xml-apis')   43
  44. GrabConfig GrabConfig systemClassLoader (boolean) using the System-ClassLoader initContextClassLoader (boolean) ContextClassLoader = CL of the current thread autoDownload (boolean) automatic downloading disableChecksums (boolean) checking checksums @GrabConfig(systemClassLoader=true) @Grab(group='mysql', module='mysql-connector-java', version='5.1.6')   44
  45. Proxy-Configuration $ groovy -Dhttp.proxyHost=<host> -Dhttp.proxyPort=<port> -Dhttp.proxyUser=<user> -Dhttp.proxyPassword=<user> yourscript.groovy JAVA_OPTS = -Dhttp.proxyHost=<host> -Dhttp.proxyPort=<port> -Dhttp.proxyUser=<user> -Dhttp.proxyPassword=<user>   45
Publicidad