How to pipe input to a process using Exec?


(Ryan Nelson) #1

I need to be able to pipe an input file to a process I’m exec’ing. The exact use case is executing a SQL file in MySQL like so:

mysql -u username -ppassword mydb < create_log_table.sql

I use project.exec() within another task:

exec {
    commandLine "cmd", "/c", "mysql", "-u", "username", "-ppassword", "mydb", "<", "create_log_table.sql"
}

That produces an error: “Process ‘command ‘cmd’’ finished with non-zero exit value 1”. I attempted a couple of variations, “< create_log_table.sql” and “mydb < create_log_table.sql” as arguments but none of those work.

Is there a recommended way to pipe an input file to an exec’ed process that I’m missing?

Ryan


(Ryan Nelson) #2

So I did a little digging, and under the hood Gradle uses java.lang.ProcessBuilder to create the process.

Based on a similar StackOverflow question, one way to handle this is to encapsulate the entire argument line in a single argument.

So my example above becomes:

exec {
    commandLine "cmd", "/c mysql -u username -ppassword mydb < create_log_table.sql"
}

This works. I guess then I wonder what the advantage of separating out the arguments is, in that case.


(Peter Niederwieser) #3

How command line arguments need to be separated depends on the expectations of the executable (‘cmd’ in this case).


(Ryan Nelson) #4

Ok, good to know, thanks.


commandLine and request of arguments
(Ryan Nelson) #5

Ok, good to know, thanks.


(Ryan Nelson) #6

Ok, good to know, thanks.


(Luke Daley) #7

Do you need to use cmd here?

Would this work?

exec {
    commandLine "mysql", "-u", "username", "-ppassword", "mydb"
    doFirst {
      inputStream = new FileInputStream(file("create_log_table.sql"))
    }
}

(Ryan Nelson) #8

Sorry, I don’t know how I missed your reply, Luke. Yes, that would work much better. I was thinking I needed to invoke a separate interpreter, but upon reflection I realized I don’t have to.