SQLCMD не работает при запуске с использованием Java - PullRequest
3 голосов
/ 07 декабря 2011

Это очень странная ситуация, но я просто не могу указать, что я делаю неправильно.

Я выполняю большой набор сценариев SQL (в основном сценариев создания таблиц). Они выполняются через Java, используя sqlcmd. Вот команда sqlcmd, которую я использую.

sqlcmd -m 11 -S SERVER -d DB -U USER -P PASS -r0 -i "SCRIPT.sql" 2> "ERRORS.log" 1> NULL

Примечание: Я использую -r0 и перенаправления, чтобы в файл журнала попадали только ошибки. Я выбрасываю все отходы.

Теперь я выполняю эту команду на Java, используя getRuntime.exec(), вот так.

Runtime.getRuntime().gc();
strCmd = "cmd /c sqlcmd -m 11 -S SERVER -d DB -U USER -P PASS -r0 -i \"SCRIPT.sql\" 2> \"ERRORS.log\" 1> NULL"
Process proc = Runtime.getRuntime().exec(strCmd);
proc.waitFor();

Примечание: Я использую cmd /c, поэтому команда запускается в своей собственной оболочке и корректно завершается. Кроме того, это помогает немедленно прочитать журнал ошибок, чтобы найти ошибки.

Проблема!

Эта команда отлично работает, когда запускается вручную в командной строке (т. Е. Таблицы создаются по назначению). Однако при выполнении через Java, как показано, сценарии запускаются, и в журналах нет ошибок, исключений и ничего. Но , при проверке в SSMS таблиц там нет!

Где я могу начать отлаживать эту проблему?

ОБНОВЛЕНИЕ: Я МОРОН

Возвращаемое значение из метода getRuntime().exec равно 1. Оно должно быть 0, что означает нормальное выполнение.

Есть какие-нибудь указатели о том, как это исправить?

ОБНОВЛЕНИЕ 2

Я посмотрел на процесс ErrorStream, и вот что у него есть.

Sqlcmd: ошибка: ошибка при открытии или работе с файлом 2> (Причина: имя файла, имя каталога или синтаксис метки тома неправильно).

Похоже, путь, который я прохожу, неверен. Журнал ошибок попадает в каталог моего профиля, который C:\Documents and Settings\my_username. Имеют ли значение места на пути? Я в любом случае цитирую их дважды!

Ответы [ 3 ]

3 голосов
/ 07 декабря 2011

Посмотрите на метод exec со строковым массивом в качестве параметра:

 java.lang.Runtime.exec(String[] cmdArray)

JavaDoc для этого метода говорит:

Выполняет указанную команду и аргументы в отдельном процессе.

Итак, первый элемент в массиве - это команда, и все ваши аргументы добавляются в массив, e. г.,

Runtime.getRuntime().exec(new String[] {"cmd", "/c", "sqlcmd ... "});

После просмотра вашего комментария и реализации exec(String) кажется, что метод exec распознает оператор канала > в качестве аргумента cmd, поскольку exec(String) разбивает командную строку на массив используя пробелы в качестве разделителей.

1 голос
/ 07 декабря 2011

У меня нет привилегий для публикации комментариев - вот что это такое - но что, если вы попытаетесь ввести поддельный идентификатор пользователя для БД? Это вызывает другой путь выполнения? Это даст вам ошибку Java? Или ошибка аутентификации в вашей БД? Кроме того, def настроить пользователя, а не пароль, и узнать из моего опыта, что если вы настроите пароль, это отличный способ заблокировать учетную запись!

Другое дело - и это может быть выстрел в темноте - но какой JRE и драйвер вы используете? Я считаю, что есть известная проблема с JRE 1.6.0.29 и sqljdbc4 JAR. У меня есть более подробная информация об этом, но мне нужно будет опубликовать ссылку, как только я доберусь до работы.

Edit:

Я знаю, что установлено, что комбо JRE / sqljdbc не является вашей проблемой, но если люди ищут и находят это, вот ссылка, о которой я говорил выше:

Driver.getConnection зависает с использованием драйвера SQLServer и Java 1.6.0_29

0 голосов
/ 07 декабря 2011

Сначала включите вывод команд log / view (поскольку exec () возвращает 1), что указывает на возможную причину проблемы. Используйте proc.getInputStream () и распечатайте содержимое в файл или консоль.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...