来自 groovy 的 ProcessGroovyMethods (UNIXProcess) 的错误结果

Bad result from groovy's ProcessGroovyMethods (UNIXProcess)

在 Ubuntu 14.04 上使用 Grails 2.4.5 org.codehaus.groovy.runtime.ProcessGroovyMethods 时:

def command = "mysqldump -h${databaseProperties.host} -u'${databaseProperties.username}' -p'${databaseProperties.password}' ${databaseProperties.name} " + table
print command
def proc = command.execute()
def oneMinute = 60000
proc.waitForOrKill(oneMinute)
if(proc.exitValue()!=0){
    println "[[return code: ${proc.exitValue()}]]"
    println "[[stderr: ${proc.err.text}]]"
    return null
}else{
    return proc.in.text.readLines()
}

我有

[[return code: 2]]
[[stderr: mysqldump: Got error: 1045: Access denied for user 'root'@'localhost' (using password: YES) when trying to connect]]

但是当我复制粘贴 printlined command 到我的 bash 时,我收到了正确的转储。怎么回事?


我也试过:

它在系统 bash 中工作,它不作为 ProcessGroovyMethod...

更新

思考一夜后,我(仍然)确信问题与您的密码有关。由于在命令行上提供密码确实不是最佳做法(mysqldump 甚至会警告您这一点),我认为您应该通过创建登录路径来改变策略。

使用以下命令创建登录路径(这是一次性步骤):

mysql_config_editor set --login-path=name --host=localhost --user=youruser --password

然后将您尝试执行的命令从 Groovy 更改为:

def command="mysqldump --login-path=name database table"

这将解决您遇到的问题并且更加安全。

原回答:

我能够重现这个问题。 String.execute() 不使用命令 shell,因此单引号被传递给 mysqldump,就像它们是您密码的一部分一样。

编辑:经过深思熟虑,我不认为Groovy的String.execute()是走这里的路,因为它出乎意料处理报价。如果您的密码不包含空格也没关系,但这可能很脆弱。

如果你需要更多的控制,你应该考虑使用ProcessBuilder:

ProcessBuilder pb = new ProcessBuilder("mysqldump", "-h${databaseProperties.host}", "-u${databaseProperties.username}", "-p${databaseProperties.password}", databaseProperties.name, table);
pb.inheritIO();
Process p = pb.start();

编辑:进一步研究,刚刚用包含空格的密码进行了测试。 command.execute() 没有正确处理这个问题,但使用 ProcessBuilder 方法有效。

这是另一个 post 解释 String.execute() 方法的一些意外行为:

Groovy: strings with embedded quotes don't execute as expected