【问题标题】:xp_cmdshell error "The filename, directory name, or volume label syntax is incorrect."xp_cmdshell 错误“文件名、目录名或卷标语法不正确。”
【发布时间】:2012-10-18 06:02:41
【问题描述】:

我正在将一些代码部署到生产环境中,这是将系统从 SQL 2000 升级到 SQL 2008。

在我的一个存储过程中遇到了一个神秘问题,它从数据库中获取一些数据,然后通过 bcp(成功)创建一些文件,然后它尝试执行几个移动命令,它们甚至都失败了尽管文件夹确实存在并且服务以系统管理员身份运行。

这是它试图执行的代码:

set @cmd_string = 'move '+ @OutPath_AllCards + '*.* '+ @ArchivePath_AllCards
delete from @tbl_xp_cmdshell_output
Insert @tbl_xp_cmdshell_output exec @error_temp = master.dbo.xp_cmdshell @cmd_string

这是我收到的错误消息

xp_cmdshell Error Executing "move H:\Transfer\CHAD\Outbound\AllCards\*.* H:\Transfer\CHAD\Outbound\AllCards\Archive\" 

返回的命令行错误是

"The filename, directory name, or volume label syntax is incorrect."

这在相同设置的 UAT 版本的数据库中工作正常

有什么建议吗?

更新:

如果源目录中没有文件,我可以重现错误。我认为源目录中可能应该有文件,但我想知道在 bcp 创建它们之前是否存在延迟,并且当它执行移动时它们还不存在?有什么想法吗?

【问题讨论】:

  • 您在末尾缺少一个“。此外,您是否知道 a) 使用 xp_cmdshell 和 b) 以系统管理员权限运行服务帐户中存在大量安全漏洞?我恳请您重新审视您的策略!
  • 我认为问题不是缺少引号,您会在输出中看到第二个较低的引号,这可能只是从结果表中解析出错误的结果.我当然知道 xp_cmdshell 的危险,但有时需要
  • 抱歉,我似乎无法编辑我的问题,所以我将把它作为评论放入 - 如果源目录中没有文件,我可以重现错误。我认为源目录中可能应该有文件,但我想知道在 bcp 创建它们之前是否存在延迟,并且当它执行移动时它们还不存在?有什么想法吗?
  • @jazza1000 为您更新了您的问题

标签: sql-server xp-cmdshell


【解决方案1】:

好吧,这里有点愚蠢的程序员(我和其他人)综合症。

发生错误是因为当您执行语句 move c:\Source*.* c:\dest 并且 source 中没有文件时,我遇到的错误将返回 ("The filename, directory name, or volume label syntax不正确。”)。

代码假定上一次运行的文件存在,因此在 bcping 新文件之前将它们移开。 bcp 并没有像我之前想象的那样首先发生。

在第一次运行作业时,上一次运行的文件不存在,所以我们收到了错误。

所以,我想解决方案是复制一份,然后在文件夹中删除,而不是尝试将其作为移动。

【讨论】:

    【解决方案2】:

    请注意,如果您从数据库服务器(在您的情况下为 SQL Server)调用外部操作系统命令,则本地计算机是该数据库服务器,不一定是您的本地计算机。

    正如您在特定示例中提到的 H: 驱动器,我假设这是一个网络映射驱动器(可能是带有用户主文件夹的驱动器)。但是,您可能会遇到这种映射存在于 UAT 数据库服务器上而不是 PROD 上的情况。当 DEV 或 UAT 服务器位于某人的本地计算机上时,这种情况并不少见,当软件进入下一个部署阶段时,事情开始出现奇怪的错误。

    在您的情况下,使用 UNC 路径(带有前导双反斜杠)而不是类似 DOS 的路径会更安全。这将使您能够独立于任何地方的驱动器映射。

    但是,我个人不喜欢将操作系统调用嵌入到数据库引擎中——它会产生混乱。我更喜欢使用 shell 脚本 (UNIX) 或命令脚本 (Windows),在其中调用存储过程(通过 isql 或 osql 或 sqlplus),然后运行其他可执行文件。使用 BCP,我看不到从存储过程运行它的任何好处 - 您仍然不能使用本地临时表,因为 BCP 会打开自己的连接。

    另外,我经常看到人们不关心检查操作是否成功的源代码。使用 BCP 来验证它是否成功需要相当大的努力(它总是返回 0 - 成功,与 isql、osql、sqlplus 等的情况相同)。您必须检查错误文件并确保它为空才能确定它没问题。所有这些东西都不适合存储过程。当然,您可以启动另一个可执行文件进行检查,但在我看来,这不是正确的方法。数据库服务器应该用于数据库操作,而不是用于完整运行应用程序。

    如果您仍然不想放弃 xp_cmdshell,我的建议是创建您自己的存储过程作为通用包装器。如果您决定更改数据库提供程序,那么迁移的痛苦将大大减少。

    【讨论】:

      猜你喜欢
      • 2018-11-07
      • 1970-01-01
      • 1970-01-01
      • 2014-06-30
      • 1970-01-01
      • 2020-04-08
      • 2021-07-24
      • 1970-01-01
      相关资源
      最近更新 更多