1

次のコマンドは、端末で使用すると正常に機能します

// ターミナル

mysql -h localhost -u root my_database -e "select count(*) from page;"

しかし、groovy スクリプトで (groovyconsole 経由で) 使用すると、実行に失敗します。代わりに、未知のコマンドが mysql に渡されたかのように、mysql の使用オプションが出力されます。

// Groovy コンソール

def p1 = 'mysql -h localhost -u root my_database -e "select count(*) from page;"'.execute()
p1.text

何が起こっているのか知っている人はいますか?

4

1 に答える 1

6

なぜそれが落ちているのかわかりませんが、私の推測では、それは mysql が選択呼び出しを引用符で囲んで処理している方法です...

回避策として、これは機能します:

[ 'mysql', 
  '-h', 'localhost',
  '-u', 'root',
  'my_database',
  '-e', 'select count(*) from page' ].execute().text

text出力を処理するより良い方法は、バッファがいっぱいになった場合のブロッキングの問題を軽減するため、( を使用するのではなく) 出力を消費することです....

何かのようなもの:

String output = new StringWriter().with { writer ->
  [ 
    'mysql', 
    '-h', 'localhost',
    '-u', 'root',
    'my_database',
    '-e', 'select count(*) from page'
  ].execute().with { proc ->
    consumeProcessOutput( writer, writer )
    waitFor()
  }
  writer.toString() 
}

println output

編集:

もちろん、いつでも JDBC を使用できます。

@GrabConfig(systemClassLoader=true)
@Grab('mysql:mysql-connector-java:5.1.21')
import groovy.sql.Sql

def rowcount = Sql.newInstance( 'jdbc:mysql://localhost/my_database', 'root', '', 'com.mysql.jdbc.Driver' ).with { sql ->
  def count = sql.firstRow( 'select count(*) from page' )[ 0 ]
  sql.close()
  count
}

println rowcount

説明

次のようなシェル スクリプトを記述した場合 (および名前を付けて保存した場合/tmp/run.sh):

#!/bin/bash

for var in "$@"
do
  echo "$var"
done

次に、実行すると:

println( '/tmp/run.sh "select count(*) from page"'.execute().text )

groovy は単純な形式の を呼び出し、次のRuntime.getRuntime.exec()ように出力します。

"select
count(*)
from
page;"

ご覧のとおり、selectビットを単語に分割するため、パラメーターはすべてめちゃくちゃになります。

代わりに呼び出す場合:

println( [ '/tmp/run.sh', '"select count(*) from page"' ].execute().text )

次のように出力されます。

"select count(*) from page"

groovy がString[]形式をRuntime.exec呼び出すので、Java はさまざまなパラメーターが何であるかを推測する必要がないため、selectすべてを 1 つのパラメーターに保持します。

これがそれを説明することを願っています:-)

于 2012-10-18T16:15:33.483 に答える