0

在 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命令复制粘贴到我的 bash 中时,我会收到正确的转储。到底是怎么回事?


我也试过:

  • mysqldump更改为完整路径:/usr/bin/mysqldump

  • 将参数作为字符串数组发送,但结果相同。

  • 将命令作为常规字符串发送以执行:

    "mysqldump -hlocalhost -u'root' -p'password' database table"
    

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

4

1 回答 1

0

更新

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

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

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

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

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

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

原始答案

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

编辑:经过进一步思考,我不认为 Groovy'sString.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方法有效。

这是另一篇文章,解释了 String.execute() 方法的一些意外行为:

Groovy:嵌入引号的字符串未按预期执行

于 2015-11-15T04:24:19.617 回答