Groovy namísto shell skriptů

Pár shell skritpů jsem už napsal - jak pro Windows tak pro Linux, ale v tomto směru se považuji za naprostou lamu a to se ještě nějakou dobu nezmění. Proto jsem fascinovaně naslouchal Dierk Königovi, který na přednášce pražského CZJUGu zmiňoval použití Groovy pro psaní shell skriptů. Vyměnit jazyk proprietárního shellu, ve kterém toho moc neumím, za multiplatformní Groovy, kde jsem na výrazně pevnější půdě, se zdá jako perfektní nápad. Vše šlo tak hladce, že neváhám podobnou věc doporučit všem, co denně kódují na JVM.

Groovy jsme už na několika projektech použili, ale nějak mi nedocvaklo, že je možné napsat libovolný Groovy skript, pustit jej z příkazové řádky a použít jej pro skriptování na vlastním systému. Jakmile nainstalujete Groovy na svůj disk a zařadíte jej do PATH proměnné, můžete odkudkoliv zavolat:

groovy cesta/ke/groovy/třídě.groovy

Groovy zařídí interpretaci skriptu a vy dostáváte k dispozici jazyk s rozsáhlými možnostmi, které znáte daleko lépe než shell. V základu tedy oproti Javě jako takové dostáváte jednu zásadní výhodu - skripty není nutné kompilovat. Stačí udělat změnu ve zdrojovém kódu a změněný soubor je možné ihned spustit. Ve svých Groovy skriptech můžete ovšem linkovat další externí knihovny a celkově disponujete mnohem větším arzenálem, než s kterým byste mohli počítat v shellu.

Na Linuxu (a MacOS?!) je možné dokonce z vlastního Groovy skriptu vytvořit přímo spustitelný soubor. Stačí na začátek Groovy skriptu přidat cestu k interpreteru zbytku souboru. V mém případě tedy stačí do Groovy skriptu přidat cestu k souboru, který spouští / interpretuje Groovy. Ukázka jednoduchého skriptu, který se po nastavení oprávnění (chmod 0744), stane samostatně spustitelným souborem:

#!/opt/Groovy/bin/groovy
println "Hello world!"

Brzy však narazíte na jednu nevýhodu, se kterou se těžko žije a tou je čas pro spuštění vlastní JVM a Groovy interpreteru. Standardně se horko těžko dostanete pod sekundu. Dierk König však v rámci přednášky ukazoval skripty, které se vykonávaly ve zlomku vteřiny. To bylo možné jen díky ...

GroovyServ

GroovyServ je Cčková implementace client-server řešení, ve kterém na pozadí žije proces s běžícím Groovy enginem, ke kterému se připojuje přes TCP/IP protokol klient, který serveru předá Groovy skript k interpretaci. Tím, že Groovy je již spuštěné, dojde k úspoře valné většiny času potřebné k interpretaci Groovy skriptu. Statistiky zrychlení jsou k dispozici na originálním GroovyServ webu - zde uvádím vlastní měření na Lenovo Thinkpad T61 (rozparsování server.xml souboru v instalaci Tomcatu):

#spuštění přes standardní GROOVY
novoj@jnonb:~/Prototypes/groovyScripts/src$ time groovy cz/novoj/infrastructure/groovy/InfrastructureScriptInvoker.groovy PWD
Current project set to: [/www/p_prj/p_fg/bm2010/]

real    0m1.370s
user    0m1.684s
sys 0m0.168s

#spuštění přes GroovyServ
novoj@jnonb:~/Prototypes/groovyScripts/src$ time groovyclient cz/novoj/infrastructure/groovy/InfrastructureScriptInvoker.groovy PWD
Current project set to: [/www/p_prj/p_fg/bm2010/]

real    0m0.148s
user    0m0.000s
sys 0m0.004s

Instalace GroovyServ je velmi jednoduchá a tudíž zde nebudu přepisovat instalační postup. Po prvním spuštění serveru je jakékoliv další spuštění groovy skriptů přes groovyclient velmi rychlé.

Debugging skriptů

Skripty v Groovy je možné snadno debugovat ve standardním Java IDE (což je věc, po které se budete v shellu těžko shánět). V případě použití GroovyServ stačí v souboru /bin/groovyserver nastavit JAVA_OPTS proměnnou. Pro inspiraci uvádím výsek z mé verze souboru:

#-------------------------------------------
# Setup other variables
#-------------------------------------------

# -server option for JVM (for performance) (experimental)
export JAVA_OPTS="$JAVA_OPTS -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9080 -server"

Pak už stačí ve vašem IDE nakonfigurovat remote debugging standardním způsobem. Opět pro inspiraci přikládám screen z IntelliJ Idey:

Prototypové skripty - ukládání a načítání server.xml konfigurací Tomcatu

Pro vlastní potřeby jsem vytvořil pár skriptů pro ukládání a načítání server.xml konfigurací Tomcat serveru. Vzhledem k tomu, že ve Forrestu pracujeme souběžně na řadě projektech a často musím přepínat z jednoho do druhého, zvykl jsem si překopírovávat zazálohované server.xml konfigurace pro cílovou doménou přes ostrou konfiguraci. Tj. mám například soubor server-trotina, který obsahuje konfiguraci webu www.trotina.cz (samozřejmě nastavenou na localhost) a který v případě potřeby překopíruju přes aktuální server.xml soubor. Po restartu Tomcata už pracuji na jiném projektu. Tato akce však vyžaduje spuštění nějakého správce souborů nebo shellu, nanavigování do složky Tomcatu, vybrání souboru a překopírování přes aktuální server.xml. Pomocí Groovy skriptů jsem si vytvořil jednoduché shell příkazy, které totéž provedou během vteřinky v rámci jediné operace:

#příkaz vytiskne aktuální doménu daného Tomcatu
novoj@jnonb:~$ gscript pwd
Using Tomcat: /opt/Apache/Tomcat_6.0
Current project set to: [/www/p_java/cps/]

#příkaz zazálohuje konfigurační soubor aktuální domény
novoj@jnonb:~$ gscript swd
Using Tomcat: /opt/Apache/Tomcat_6.0
Saved file: /opt/Apache/Tomcat_6.0/conf/backup/server-cps.xml

#příkaz obnoví konkrétní soubor ze zálohy, 
#skript inteligentně vyhledává konfiguraci podle shody názvu s argumentem volání
novoj@jnonb:~$ gscript rd cps
Using Tomcat: /opt/Apache/Tomcat_6.0
Found these matching files:
---------------------------------------------------
1 pts. : server-vodafoneic.xml, server-agcom.xml, server-hodnoceni-olivka.xml
2 pts. : server-kb_sec.xml, server-praguewelcome.xml, server-vodafoneic-public.xml
3 pts. : server-specialsettings.xml, server-jakchutnauspech.xml
9 pts. : server-cpsprototype.xml
1000 pts. : server-cps.xml
---------------------------------------------------
Restored file: /opt/Apache/Tomcat_6.0/conf/backup/server-cps.xml

Zdrojové kódy včetně shellového skriptu gscript jsou uloženy na GitHubu, takže pokud byste měl někdo podobný use-case jako já, můžete využít mé hotové práce. Zajímavý je minimálně zmíněný shell skript, protože díky chybě Groovy, není možné jednoduše použít wildcard znaků v linkování připojených JARů ze složky.

Pozn.: na Groovy jsem převedl i další skripty pro hromadnou konverzi kódování textových souborů a odstranění BOM z UTF-8 popsaných v článku Až budete chtít někdy dávkově konvertovat kódování souborů …

Zdrojové soubory: GitHub

Souhrnně

Každý z nás sem tam potřebuje napsat shell skript a Groovy má pro nás Java vývojáře řadu nesporných výhod:

  • multiplatformní vývoj - skript, který napíšu pro Linux může běžet bez problémů i na Win platformě
  • řada pokročilých funkcí k dispozici "out of the box" (XML processing, Ant funkce, databáze)
  • použitelnost stávající znalostí z Java vývoje
  • objektový přístup k shell skriptům
  • možnost využití existujících Java knihoven (Apache Commons atp.)
  • použití Groovy goodies - closures, řada funkcí ulehčující práci s Java objekty
  • programovat v Groovy je zábava a toto je jedna z bezpečných možností, jak přičichnout ke Groovy i v případě, že jej nemůžeme používat pro produkční kód :)

Poznámky na okraj

Dierk König také na své přednášce zmiňoval optimalizovaný vyhledávač (respektive customizovaný vyhledávací formulář Google) pro Groovy výrazy http://groovysearch.org/. Což by mohlo taktéž řadu z nás poměrně zajímat.