【问题标题】:SQLCMD not working when run using Java使用 Java 运行时 SQLCMD 不起作用
【发布时间】:2011-12-07 10:25:48
【问题描述】:

这是一个非常奇怪的情况,但我无法指出我做错了什么。

我正在执行一大堆 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 并重定向以确保只有错误进入日志文件。我丢弃了所有的 STDOUT。

现在我在 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,以便命令在自己的shell 中运行并优雅退出。此外,这有助于立即读取错误日志以查找错误。

问题!

当在命令提示符下手动运行时,此命令可以完美运行(即按预期创建表)。但是,如图所示通过 Java 执行时,脚本会运行,并且没有错误、没有异常、日志中没有任何内容。 但是,在签入 SSMS 时,表格不存在!

我什至从哪里开始调试这个问题?

更新:我是个白痴

getRuntime().exec方法的返回值为1,应该是0,表示正常执行。

关于如何解决这个问题的任何指示?

更新 2

我查看了进程的 ErrorStream,这就是它所具有的。

Sqlcmd:错误:打开或操作文件 2 时出错> (原因:文件名、目录名或卷标语法是 不正确)。

看起来我经过的路径是错误的。错误日志进入我的配置文件目录,即C:\Documents and Settings\my_username。路径中的空格重要吗?反正我是双引号!

【问题讨论】:

  • 你试过从进程中读取输出流吗?
  • @RogerLindsjö 好的,所以我尝试获取 ErrorStream,它显示错误“Sqlcmd:错误:打开或操作文件 2 时发生错误>(原因:文件名、目录名或卷标语法不正确”
  • 你必须重定向流吗?处理这些解析应该是 cmd 的工作。但是,如果您完全跳过重定向并处理 Java 格式的流,您可以使其工作吗?
  • 我不想对使用 Java 的流做任何事情。所以我决定让 SQLCMD 处理它。现在这个问题突然出现了,我利用 ErrorStream 来查看它。另外,看看我的第二次更新。

标签: java sql sql-server-2008 sqlcmd


【解决方案1】:

看看以字符串数组为参数的 exec 方法:

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

这个方法的 JavaDoc 说:

在单独的进程中执行指定的命令和参数。

因此,数组中的第一项是命令,所有参数都附加到数组中,例如。 g.,

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

在查看您的评论和exec(String) 的实现之后,exec 方法似乎将管道运算符> 识别为cmd 的参数,因为exec(String) 将命令字符串拆分为一个数组使用空格作为分隔符。

【讨论】:

  • 哇,学习这么多关于运行时的东西真是令人兴奋!所以我尝试将整个命令作为一个单元素数组传递,比如Runtime.getRuntime().exec(new String[] {strCmd});。现在 ErrorStream 为空,但仍未创建表!
  • 您是否尝试过传递一个包含三个元素的数组? 0. 命令cmd 1. cmd 的第一个参数:/c 2. cmd 的第二个参数:“sqlcmd -m ...”
  • 好的,我试过了。我收到错误“访问被拒绝”。在错误流中。 sqlcmd 会不会抛出这个错误?
  • 嗯,只尝试 sqlcmd 部分,暂时忽略日志文件。似乎 sqlcmd 返回带有前缀“sqlcmd:”的错误消息。
  • 这行得通!我通过了sqlcmd -m 11 -S SERVER -d DB -U USER -P PASS -i "SCRIPT.sql" 并且它有效!但是日志记录本质上是为了我的目的=[
【解决方案2】:

我没有发布 cmets 的权限 - 就是这样 - 但是如果您尝试为数据库输入一个虚假的用户 ID 会怎样?这会导致不同的执行路径吗?这会给你一个Java错误吗?还是您的数据库中的身份验证错误?此外,def 调整用户,而不是密码,根据我的经验,如果您调整密码,这是锁定帐户的好方法!

另一件事 - 这可能是在黑暗中拍摄 - 但是您使用的 JRE 和驱动程序是什么?我相信 JRE 1.6.0.29 和 sqljdbc4 JAR 存在一个已知问题。我对此有更多详细信息,但我必须在开始工作后发布链接。

编辑:

我知道已经确定 JRE/sqljdbc 组合不是您的问题,但如果人们搜索并找到这个,这里是我上面提到的链接:

Driver.getConnection hangs using SQLServer driver and Java 1.6.0_29

【讨论】:

  • Matt,我使用的是 JRE 1.6.0.03 和 sqljdbc4 JAR。还要检查我的第二次更新!
【解决方案3】:

首先启用日志/查看命令输出(因为 exec() 返回 1),这将指出问题的可能原因。 使用 proc.getInputStream() 并将内容打印到文件或控制台。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-02
    • 1970-01-01
    • 2019-01-08
    • 2014-11-07
    • 2021-06-12
    • 2016-11-01
    • 2016-08-05
    • 1970-01-01
    相关资源
    最近更新 更多