通过Powershell或BATCH串行执行symstore

3
我们正在努力将一步骤集成到我们的持续集成(CI)服务器(CruiseControl.NET)中。我们希望将构建过程中生成的调试符号*.pdb注册到Microsoft符号服务器中。由Microsoft实现,符号服务器是Visual Studio用于查找C++/C#可执行文件的*.pdb调试符号的目录结构。Microsoft提供一个命令symstore,它接受一个目录中的调试符号,并适当地填充中央符号存储目录。
问题在于symstore明确表示不安全并发运行。
我们可以尝试哪些方法或策略来通过BATCH或Powershell脚本禁止并发执行symstore命令?
我们对方法有弹性,但因为我们在Windows平台上运行,BATCH和Powershell是首选解决方案。
澄清:
对于我们的用例,symstore需要从两个不同的CI服务器运行,它们将在共享网络驱动器上保存符号。
资源:

symstore:: http://msdn.microsoft.com/en-us/library/windows/desktop/ms681417(v=vs.85).aspx


2
您需要在不同进程间在同一台计算机上运行 symstore 吗?还是需要在不同计算机上运行 symstore,并管理位于中央计算机上的符号存储? - Aaron Jensen
通过使用TFS及其构建过程模板,可以同步访问符号存储库。请参阅此处的“SharedResourceScope Activity”:http://blogs.msdn.com/b/adamroot/archive/2009/06/17/source-server-and-symbol-server-features-in-team-foundation-server-2010-beta-1.aspx - M.A. Hanin
3个回答

6
您可以使用锁定的文件作为简单的信号量来串行化事件。当您在批处理文件中将stdout重定向到文件时,它会在该文件上建立一个独占写锁。没有其他进程可以打开同一个文件以进行写访问。无论如何结束(干净退出、CTRL-C、异常失败等),锁都会自动释放。
批处理文件可以尝试将9重定向到锁定文件,如果失败,就会循环回来直到成功。symstore命令仅在锁定期间运行。使用非标准文件句柄(流?)以使锁定不会干扰stdin、stdout或stderr处理。
所以您只需要确保永远不要直接调用symstore。而是始终通过批处理脚本调用它。类似以下内容(serializeSymstore.bat):
@echo off
setlocal

:loop

:: Save stderr definition and redirect stderr to nul
:: to hide possible redirection error when establishing lock.
8>&2 2>nul (

  %= Attempt to establish the lock and restore stderr =%
  9>"\\centralServer\somePath\symstore.lock" 2>&8 (

    %= If got here then lock is established throughout all commands =%
    %= in this set of parentheses.                                  =%

    %= Execute your command =%
    symstore %*

    %= Save the return code =%
    call set "rtnCd=%%errorlevel%%"

    %= The next command is a very fast way to clear the ERRORLEVEL. =%
    %= We don't want symstore failure to trigger a loop.            =%
    (call )
  )

) || (
  %= If entered here then failed to establish lock.                 =%
  %= Wait 1 second and then loop back to retry.                     =%
  %= Replace with PING delay if TIMEOUT not universally available.  =%
  timeout 1 /nobreak >nul
  goto loop
)

:: Exit with appropriate return code
exit /b %rtnCd%

没有注释,代码就变成了一小段。
@echo off
setlocal

:loop
8>&2 2>nul (
  9>"\\centralServer\somePath\symstore.lock" 2>&8 (
    symstore %*
    call set "rtnCd=%%errorlevel%%"
    (call )
  )
) || (
  timeout 1 /nobreak >nul
  goto loop
)
exit /b %rtnCd%

我发现这种原始且简单的策略在许多项目中非常有效。我必须承认,我没有在远程机器上测试锁定和释放特性。但我相信只要所有机器都是Windows,它应该是可靠的。
我知道唯一的缺点是没有FIFO队列。如果收到多个重叠的请求,那么哪个进程可以接下来运行就是随机的。但进程将被序列化。
编辑:我在编辑之前阅读了splattered bits的原始答案。他质疑文件锁定在远程机器上是否可靠。我做了一些快速的Google搜索,似乎UNC路径上的文件锁定存在一些问题。如果遇到问题,您可能更好地将其重定向到映射驱动器字母上的文件,而不是直接通过UNC路径访问。这全都是理论 - 我没有进行任何测试。请务必在承诺使用此解决方案之前进行充分的测试。请注意,PUSHD是一个方便的方法,可以临时为UNC路径分配驱动器号,而无需知道可用的驱动器号。POP​​D将取消映射驱动器的分配。

这正是我所希望的范例...一个提供互斥性的批处理/PowerShell包装器。对一些虚拟机进行了初步测试,效果良好。我会进行更多测试,然后接受! - Eric Webb
@EricWebb - 请查看我对回答的编辑 - 在 UNC 路径上可能存在锁定问题。 - dbenham
重要的不是路径是UNC还是网络驱动器,而是它是一个网络文件系统。当通过网络连接访问文件时,Windows无法保证文件锁定。 - Aaron Jensen
@splatteredbits - 目标机器使用的操作系统或文件系统是否重要?你有什么参考资料可以让我看看吗?我想学习更多。我相信有一些配置可以支持这个,但我也能看到其他一些可能不行。在我的随意搜索中,我发现映射驱动器可以解决一些针对UNC路径的锁定问题。 - dbenham
@dbenham 不是的。Mercurial团队的建议是针对Windows SMB文件共享的。 - Aaron Jensen
显示剩余3条评论

0
为了锁定对网络驱动器的访问权限,您需要一个第三方工具来连接您的CI服务。这个第三方工具将处理对网络驱动器的访问权限。第三方工具可以是以下之一:
  • MSMQ
  • 数据库表中的一行
  • 运行 symstore 的符号服务器上的 WCF 服务,您的 CCNet 构建将与其通信以触发 symstore
  • 安装在符号服务器上的 CCNet,有一个可以远程触发的项目/作业
  • 符号服务器上的计划任务,可以从您的 CI 服务器远程触发

1
如果这两个进程在不同的主机上运行,那么这并不能解决问题。 - PA.
@PA 原始问题没有提及任何关于跨机器要求的内容。 - Aaron Jensen
你是对的,它确实不行,我只是从之前类似的情况中做出了假设(顺便说一下,我没有给你的答案投反对票)。 - PA.
@splatteredbits 这看起来是一个不错的解决方案!在得到初始答案(和您的澄清请求)之后,我意识到我需要澄清我的要求,因为这会大大改变解决方案。但是,如果我的要求是在_一台_机器上阻止并发,我认为这是正确的。 - Eric Webb
@EricWebb 我已经更新了我的答案,因为在不同的计算机之间使用互斥锁是行不通的。 - Aaron Jensen

-1
使用共享目录中的文件作为信号量,以避免并发执行。
:checkfile
if exist %cidir%\sem.txt goto :wait10secs
echo gotit! >%cidir%\sem.txt
doit
del %cidir%\sem.txt
goto :eof
:wait10secs
ing 192.0.2.2 -n 1 -w 10000 > nul
goto :checkfile

准备好调试所有批处理可能失败的奇怪方式和所有恶劣的竞争条件。


1
这里对我来说看起来像是竞争条件。为了使其正常工作,检查 sem.txt 的存在并创建(锁定)它需要保证原子性,或者如果 sem.txt 已经存在则创建失败。 - Eric Webb
是的,我把这个详细实现留给了OP或者一个第二个SO问题。 - PA.
1
那个细节对于所述的问题是基本的!话虽如此,关于跨机器并发的观点是一个很好的观点。 - Eric Webb
你说得没错,但我们没有足够的信息来判断避免并发的基本程度。可能symstore只会拒绝或忽略第二次尝试,也可能是更严重的情况。这取决于OP自己评估,并在需要帮助时回到我们这里。 - PA.
通过对文件进行锁定而不是依赖于文件的存在来避免竞态条件。请参见我的回答 - dbenham

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接