21
Groovy Shell Scripting 2015 JGGUG G*Workshop 2015/06/26 上原潤二 (NTT ソフトウェア )

Groovy Shell Scripting 2015

  • Upload
    -

  • View
    369

  • Download
    4

Embed Size (px)

Citation preview

Page 1: Groovy Shell Scripting 2015

Groovy Shell Scripting 2015JGGUG G*Workshop 2015/06/26 上原潤二(NTTソフトウェア)

Page 2: Groovy Shell Scripting 2015

わたくしは上原潤二(@uehaj) NTTソフトウェア(株)Grails推進室 JGGUG運営委員

書いたり プログラミングGROOVY(技術評論社) Grails徹底入門(翔泳社) ブログ「Grな日々」

Page 3: Groovy Shell Scripting 2015

Groovyスクリプト使ってますか?Groovyスクリプトとは クラス定義に囲まれていない、トップレベルの文や関数定義から構成 binding変数が使える コンパイルしない

Page 4: Groovy Shell Scripting 2015

スクリプトは日々作業に便利編集してすぐ再実行できる

コンパイルやIDEやGradleとかは不要

おおげさなインストールも不要(置くだけ)

でも…

Page 5: Groovy Shell Scripting 2015

いくつか問題がある。プロセスの扱い

クラスパス問題

Page 6: Groovy Shell Scripting 2015

(問題1) プロセスの扱い

Page 7: Groovy Shell Scripting 2015

プロセス起動の諸問題

"ls -l".execute() 出力は?

println("ls -l".execute().text) 標準エラーはどこへ?

"ssh host.example.com ls".execute()

パスワードを聞いてきたら何がおきる?

Page 8: Groovy Shell Scripting 2015

ProcessBuilder#inheritIO()

本日のネタ:これをGroovyらしい形で有効活用しようではないか

Page 9: Groovy Shell Scripting 2015

String.metaClass.execString.metaClass.exec0  =  {    def  st  =  new  StringTokenizer(delegate)    new  ProcessBuilder(st.collect()).inheritIO().start()  }  

"login".exec0().waitFor()  println  "done"  

waitForはProcessのメソッド

Page 10: Groovy Shell Scripting 2015

パイプString.metaClass.or  =  {  String  rhs  -­‐>          delegate.execute()  |  rhs.execute()  }  Process.metaClass.or  =  {  String  rhs  -­‐>          delegate  |  rhs.execute()  }  String.metaClass.or  =  {  Process  rhs  -­‐>          delegate.execute()  |  rhs  }  

"echo  123abc"  |    "tr  'a-­‐z'  'A-­‐Z'"  |    "grep  B".exec(input:Redirect.PIPE)

色付きGrepが機能(isatty)

https://github.com/uehaj/groovy-shell-scripting-examples

Page 11: Groovy Shell Scripting 2015

リダイレクト@groovy.transform.BaseScript(cmd.Base1)  import  java.lang.String  

"sed  -­‐e  s/[a-­‐z]/A/g".exec(input:"input.txt",                                                      output:"output.txt")  

println  new  File("input.txt").text  println  new  File("output.txt").text

https://github.com/uehaj/groovy-shell-scripting-examples

Page 12: Groovy Shell Scripting 2015

メソッド追加はいつやるの?staticイニシャライザ

不安

拡張メソッド?

Jarに梱包する必要がありスクリプト用としては面倒

Page 13: Groovy Shell Scripting 2015

@BaseScriptで簡単確実Since: Groovy 2.2.0

package  cmd  

import  java.util.StringTokenizer  import  static  java.lang.ProcessBuilder.Redirect  

abstract  class  Base0  extends  Script  {          abstract  Object  runScript()  

       Object  run(){                  String.metaClass.exec  =  {                          def  st  =  new  StringTokenizer(delegate)                          new  ProcessBuilder(st.collect()).inheritIO().start()                  }                  String.metaClass.or  =  {  String  rhs  -­‐>  

                       delegate.execute()  |  rhs.execute()                  }                  Process.metaClass.or  =  {  String  rhs  -­‐>                          delegate  |  rhs.execute()                  }                  String.metaClass.or  =  {  Process  rhs  -­‐>                          delegate.execute()  |  rhs                  }                  runScript()          }  }

@groovy.transform.BaseScript(cmd.Base0)  import  java.lang.String  

"login".exec().waitFor()  println  "done"

Page 14: Groovy Shell Scripting 2015

@BaseScriptの有用性DSLを作るための手軽な仕掛け置き場

methodMissing, getProperty…

Groovyスクリプトでは特定の名前の変数を定義(クロージャ、マップ、…)

それに対してBase側で任意の処理

Page 15: Groovy Shell Scripting 2015

(問題2) クラスパス問題

Page 16: Groovy Shell Scripting 2015

スクリプトのクラスパス問題(1 of 2)スクリプトを実行可能プログラムのように起動 そのとき、以下を読めるようにクラスパスを指定したい @BaseSciriptの対象 スクリプトから利用するクラス

問題: shebangは$0を解釈しない

Page 17: Groovy Shell Scripting 2015

スクリプトのクラスパス問題(2 of 2)スクリプトの場所($0)相対で読みこんで欲しい スクリプトごとにCLASSPATH環境変数に追加したくない😔

すべてを~/.groovy/libにぶちこむのはもっと嫌😖

Perl, Ruby, Pythonなどではあたりまえの話 Groovyスクリプトを呼び出すShell Script/.batを書く

あきらかな負け😖

Page 18: Groovy Shell Scripting 2015

Linux,MacOS以下のようにすると勝つる😃

#!/bin/bash  //usr/bin/env  groovy  -­‐cp  "`dirname  $0`"  "$0"  $@;  exit  $?  

@groovy.transform.BaseScript(cmd.Base1)  …

├── thisscript.groovy └── cmd/ └── Base1.groovy

Page 19: Groovy Shell Scripting 2015

WindowsスクリプトはPATHの通ったところに置いた上で「管理者として実行」したコマンドプロンプトで以下を実行

ただし、

PATH配下をすべて見てしまう😟

「ダブルクリックしてスクリプト起動」に対応しない

assoc  .groovy=groovyscript  ftype  groovyscript=C:\groovy-­‐2.4.1\bin\groovy.bat  -­‐cp  "%PATH%”  "%1"  %*

Page 20: Groovy Shell Scripting 2015

まとめ日々作業はGroovyで片付けよう!!

おまけ

docopt.java便利

Page 21: Groovy Shell Scripting 2015

参考リンクなど@BaseScriptアノテーションはscriptをインクルードするのに使えますhttp://uehaj.hatenablog.com/entry/2014/04/25/220853

https://github.com/docopt/docopt.java

サンプルコードhttps://github.com/uehaj/groovy-shell-scripting-examples