一个远程 Jenkins 代理无法知道给定的工作区目录是否正在被同一台机器上运行的另一个代理使用。对于通过卷挂载共享公共目录的基于 docker 的代理也是如此。理想情况下,在同一台机器上工作的所有代理都可以通过某种方式相互交谈,以防止踩到对方的脚趾(例如,工作区中的锁定文件在工作终止时被删除),但目前情况并非如此。
解决方案 #1:独特的构建工作区
如果我们使用 Jenkins 管道,我们可以在每个构建的基础上将一个唯一的子目录附加到工作区目录。该解决方案干净、简单且易于实施。
agent {
node {
customWorkspace "${env.BUILD_NUMBER}"
}
}
参考:https ://www.jenkins.io/doc/book/pipeline/syntax/#agent
解决方案 #2:独特的代理工作区
如果这是不可能或不可取的,另一个可能的解决方案是更改 Jenkins 代理本身的根工作目录,这可以通过向代理的启动命令提供一个附加参数来完成:
-workDir FILE : Declares the working directory of the
remoting instance (stores cache and logs by
default)
资源:java -jar agent.jar -help
当在同一台机器上动态启动多个代理时,我们可以将此-workDir
值设置为更具唯一性的值,以便为每个代理提供自己的工作目录,从而有效地减少工作空间冲突。像这样的东西应该很好用:
java -classpath agent.jar hudson.remoting.jnlp.Main -headless \
-workDir /var/lib/jenkins/workspace/$(date +%3N) ...
神奇之处在于$(date +%3N)
,它将系统时钟纳秒返回到三位数的精度。我们可能希望使用更多或更少的数字,因为有一个折衷:更高的精度将导致更高的工作空间目录的最大数量,但会降低工作空间冲突的风险;较低的精度会产生相反的效果 - 更少的目录,增加的碰撞风险。
此命令的配置方式将根据您的 Jenkins 设置而有所不同。例如,我们在 Jenkins 2.249.3 上使用Docker Swarm 插件(v1.9)。我们的代理命令可在管理 Jenkins >> 管理节点和云 >> 配置云 >> Docker Swarm 云配置 >> Docker 代理模板 >> 命令进行配置。
参考:https ://man7.org/linux/man-pages/man1/date.1.html