通过Powershell或BATCH序列化symstore的执行

我们正在努力整合一个步骤到我们的持续集成(CI)服务器(CruiseControl.NET)中。 我们希望将从构build过程生成的debugging符号*.pdb注册到Microsoft Symbol Server中。 由Microsoft实现,符号服务器是Visual Studio用于查找C ++ / C#可执行文件的*.pdbdebugging符号的目录结构。 Microsoft提供了一个命令symstore ,它将debugging符号放在一个目录中,并根据需要填充中央符号存储目录。

symstore的麻烦是明确指出并行运行并不安全。

我们可以尝试通过BATCH或Powershell脚本禁止同时执行symstore命令的方法或策略是什么?

我们在方法上很灵活,但是因为我们在Windows平台上运行,所以BATCH和Powershell是首选解决scheme。

澄清:

对于我们的使用情况, symstore需要从两个不同的CI服务器运行,这会将符号保存在一个通用的networking驱动器上。

资源:

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

您可以使用锁定的文件作为简单的信号量来序列化事件。 当您将stdout重定向到批处理文件中的文件时,它会在该文件上建立一个独占写入锁定。 没有其他进程可以打开相同的文件进行写访问。 当进程结束时,锁将自动释放,不管它如何结束(清理出口,CTRL-C,异常失败等)

批处理文件可以尝试将9重定向到锁定文件,如果失败,则循环直到成功。 symstore命令只在锁定到位时运行。 使用非标准的文件句柄(stream?),以便锁不会干扰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队列。 如果收到多个重叠的请求,那么这个抽签的随机运行就是下一个进程的下一个进程。 但是这个过程将被序列化。

编辑:
在编辑之前,我已经阅读了飞溅的原始答案。 他质疑远程机器上的文件锁定是否可靠。 我做了一些快速的Google搜索,似乎在UNC路径上有文件锁定的问题。 如果遇到问题,您可能会有更好的运气重定向到映射的驱动器号上的文件,而不是直接通过UNC路径。 这都是理论 – 我没有做过测试。 在提交此解决方案之前,请务必做足够的测试。 请注意,PUSHD是临时将驱动器号分配给UNC路径而不知道可用驱动器号的便捷方式。 POPD将取消映射驱动器分配。

为了锁定对网络驱动器的访问权限,您需要一个CI服务通讯的第三方。 然后这个第三方将处理对网络驱动器的访问。 这第三方可能是:

  • MSMQ
  • 在数据库表中行
  • 运行symstore符号服务器上的WCF服务,您的symstore构建会与之通信以触发symstore
  • 符号服务器上的CCNet,可以远程触发一个项目/作业
  • 符号服务器上可以从CI服务器远程触发的预定作业

使用共享目录中的文件作为信号量以避免并发执行。

 :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 

准备调试你的批次可能会失败的所有奇怪的方式和所有讨厌的赛车条件。