Плохой результат от Groovy's ProcessGroovyMethods (UNIXProcess)

При использовании Grails 2.4.5 http://docs.groovy-lang.org/latest/html/api/org/codehaus/groovy/runtime/ProcessGroovyMethods.html в Ubuntu 14.04:

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

  • отправка аргументов в виде массива String, но с тем же результатом.

  • отправка команды в виде обычной строки для выполнения:

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

это работает в системе Bash, это не как ProcessGroovyMethod...

1 ответ

Решение

Обновление:

Подумав об этом в одночасье, я (до сих пор) убежден, что проблема связана с вашим паролем. Поскольку ввод пароля в командной строке действительно не рекомендуется (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's 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 метод работает.

Вот еще один пост, объясняющий некоторые неожиданные действия метода String.execute():

Groovy: строки со встроенными кавычками не выполняются должным образом

Другие вопросы по тегам