groovy on the shell
TRANSCRIPT
GROOVY ONTHE SHELL
SHELLSCRIPTING WITH GROOVYAlexander Klein / http://codecentric.de [email protected]
0
ALEXANDER (SASCHA) KLEIN
Principal Consultantcodecentric AG
Stuttgart
Groovy, JavaFX, UI / UX
Griffon committer
[email protected]@saschaklein
http://gplus.to/karfunkel
USING THE DEFAULTENVIRONMENT
#!/usr/bin/env groovy
DEFINING THE CLASSPATH#!/usr/bin/env groovy -cp myjar.jar
USING SYSTEM VARIABLES#!/usr/bin/env groovy -cp ${HOME}/bin
DEFINING SYSTEM VARIABLES#!/usr/bin/env VAR1=value1 VAR2=value2 groovy
BUTDOES NOT WORK ON LINUX
Alternative script for /usr/bin/envWithout defining system variables
#!/bin/bashARGS=( $1 ) # separate $1 into multiple space-delimited arguments.shift # consume $1PROG=`which ${ARGS[0]}` # find path for executableunset ARGS[0] # discard executable nameARGS+=( "$@" ) # remainder of arguments preserved "as-is".# iterate array and expand variablesdeclare -a PARAMSfor i in "${ARGS[@]}" do PARAMS=("${PARAMS[@]}" "`eval "echo $i"`") doneexec $PROG "${PARAMS[@]}" # execute the command
INSTALLATIONWINDOWS
GroovyServ is part of the Groovy Windows-Installer
LINUXgvm install groovyserv
MAC OS Xbrew install groovyserv
BINARY PACKAGE$ cd /tmp$ unzip groovyserv-1.0.0-bin.zip$ groovyserv-1.0.0-bin/bin/setup.sh
export PATH=/tmp/groovyserv-1.0.0/bin:$PATH
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("."))
RESULT ACCESSprintln "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 }
PROCESS CONTROLProcess 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()
PROCESS OUTPUTProcess process = "myCommand".execute()def out = new StringBuffer()def err = new StringBuffer()process.waitForProcessOutput( out, err )if( out.size() > 0 ) println outif( err.size() > 0 ) println err
def p = "rm -f foo.tmp".execute([], tmpDir)p.consumeProcessOutput() // Prevent blocking by small bufferp.waitFor()
PIPING"less temp.sh".execute().pipeTo("grep Detected".execute()).text
def proc1 = "less temp.sh".execute()def proc2 = "grep Detected".execute()proc1 | proc2println proc2.text
WILDCARDS"ls *.java".execute() // won't work
"sh -c ls *.java".execute() // Shell resolves the wildcard
SHELL HELPER Iclass 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 }
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) }}
SHELL HELPER IIIdef shell = new Shell()shell.call("mkdir /tmp/groovy")shell.call("echo 123 >> /tmp/groovy/test")shell.dir("/tmp/groovy").call("echo \$HOME >> test2")shell.eachLine("ls ."){ println "- $it -"}shell.eachLine("cat test2"){ println "- $it -"}
HELPFULL STUFFACCESSING SYSTEM-VARIABLES
println System.env.PWD
ACCESSING SYSTEM-PROPERTIESprintln System.properties.'user.dir'
GET YOUR PIDimport java.lang.management.*println ManagementFactory.runtimeMXBean.name.split('@').first().toInteger()
PARSING COMMANDLINEARGUMENTS
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" }
A SAMPLEusage: 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
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')}
THE CODE IIdef 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"}
GRAPEGROOVY ADAPTABLE PACKAGING ENGINE
@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
Cachedirectory ~/.groovy/grape
@GRAB ANNOTATION IAnnotatable everywhere
often seen at import statementsgroup (String)
Maven groupId or Ivy organizationmodule (String)
Maven artifactId or Ivy artifactversion (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
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 { ...}
REPOSITORIESConfiguration in ~/.groovy/grapeConfig.xml
Grape cache -> ~/.groovy/grapesMaven Local -> ~/.m2/repositoryJCenter (includes Maven Central)
Codehaus.org
IBiblio
Java.net
http://jcenter.bintray.com
http://repository.codehaus.org
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')
EXCLUDE TRANSITIVE DEPENDENCIES@Grab('net.sourceforge.htmlunit:htmlunit:2.8')@GrabExclude('xml-apis:xml-apis')
GRABCONFIG@GrabConfig(systemClassLoader=true)@Grab(group='mysql', module='mysql-connector-java', version='5.1.6')
GrabConfigsystemClassLoader (boolean)
using the System-ClassLoaderinitContextClassLoader (boolean)
ContextClassLoader = CL of the current threadautoDownload (boolean)
automatic downloadingdisableChecksums (boolean)
checking checksums
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>
QUESTIONS ?Alexander (Sascha) Klein
codecentric AG
Curiestr. 270563 Stuttgart
tel +49.711.67400-328
mobile [email protected]
@saschaklein
http://www.codecentric.dehttp://blog.codecentric.de