C0deAttack
C0deAttack

Reputation: 24667

Groovy Process executing

The following command works fine when used on a terminal

// Terminal

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

But when used in a groovy script (via groovyconsole) it fails to execute. Instead the mysql usage options are printed, as if some unknown command was passed to mysql.

// Groovy Console

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

Any one know what's up with that?

Upvotes: 1

Views: 1628

Answers (1)

tim_yates
tim_yates

Reputation: 171084

Not sure why it's falling over, my guess is it is the way mysql is handling the select call in quotes...

As a workaround, this works:

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

A nicer way of handling the output is to consume it (rather than use text) as this should alleviate any blocking issues should your buffers fill up....

Something like:

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

Edit:

Of course, you can always just use 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

Explanation

If you write a shell script like this (and save it as /tmp/run.sh):

#!/bin/bash

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

Then, when you run:

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

groovy calls the simple form of Runtime.getRuntime.exec(), and it prints out:

"select
count(*)
from
page;"

As you can see, the parameters get all messed up, as it separates the select bit into words.

When you instead call:

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

It prints out:

"select count(*) from page"

As groovy calls the String[] form of Runtime.exec so java doesn't have to guess what the different parameters are, so keeps the select all in one parameter.

Hope this explains it :-)

Upvotes: 6

Related Questions