来自 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 时,我收到了正确的转储。怎么回事?
我也试过:
将mysqldump更改为完整路径:/usr/bin/mysqldump
将参数作为字符串数组发送,但具有相同的
结果.
将命令作为要执行的常规字符串发送:
"mysqldump -hlocalhost -u'root' -p'password' database table"
它在系统 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
在 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 时,我收到了正确的转储。怎么回事?
我也试过:
将mysqldump更改为完整路径:/usr/bin/mysqldump
将参数作为字符串数组发送,但具有相同的 结果.
将命令作为要执行的常规字符串发送:
"mysqldump -hlocalhost -u'root' -p'password' database table"
它在系统 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