您可以将锁定的文件用作简单的信号量来序列化事件。当您将 stdout 重定向到批处理文件中的文件时,它会在该文件上建立排他写锁。没有其他进程可以打开同一个文件进行写访问。进程完成时,锁将自动释放,无论它如何结束(干净退出、CTRL-C、异常失败等)
批处理文件可以尝试将 9 重定向到锁定文件,如果失败,则循环返回直到成功。symstore 命令仅在锁定到位时运行。使用非标准文件句柄(流?),以便锁不会干扰标准输入、标准输出或标准错误处理。
所以你只需要确保你从不直接调用 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 路径的便捷方法。POPD 将取消映射驱动器分配。