从 Jenkins 管道查询 MS Sql 服务器

Querying MS Sql Server from a Jenkins Pipeline

我一直在 docker 容器 (https://hub.docker.com/r/jenkins/jenkins) 中使用 Jenkins (2.289.3)。 Jenkins 2.312 的下一次更新将 docker 容器从 Java 8 迁移到 Java 11。

我有一些管道使用 sourceforge jdbc 驱动程序来查询 SQL 服务器 (http://jtds.sourceforge.net/)

示例:

import java.sql.DriverManager
import groovy.sql.Sql

con = DriverManager.getConnection('jdbc:jtds:sqlserver://servername', 'user', 'password');
stmt = con.createStatement();

为了使这个工作,在 Java 8 上的 Docker 容器中,我在 docker 容器

上 运行
cp jtds-1.3.1.jar ${JAVA_HOME}/jre/lib/ext

加载 jar 以在 Jenkins 中使用。此方法不再存在 Java 11.

管道似乎添加了@Grab 语法,例如

@Grab(group='net.sourceforge.jtds', module='jtds', version='1.3.1')

如果我将它添加到我的管道中,我可以看到 Jars 下载到 /var/jenkins_home/.groovy/grapes/ 但它似乎并没有真正加载 jar

java.lang.ClassNotFoundException: net.sourceforge.jtds.jdbc.Driver 要么 java.sql.SQLException: No suitable driver found for jdbc:jtds:sqlserver://servername 取决于我 运行 的命令。无论哪种方式,这似乎是由于未加载 jar。

所有 groovy 示例都使用

@GrabConfig(systemClassLoader=true)

但这似乎在管道中不受支持。

我考虑过使用命令行客户端,但我需要解析查询结果,但我还没有看到适合此操作的工具(即可以将结果加载到 json 文件或类似文件)

我也试过在 docker 容器中设置 -classpath 参数,例如

ENV JAVA_OPTS=-classpath /var/jenkins_home/test/jtds-1.3.1.jar

运行 ps 在 docker 容器中,我可以看到 java 进程 运行 指定了类路径命令行选项,但是它似乎并没有实际加载 jar 以供使用。

我对如何让它工作有点迷茫,有人可以帮忙吗?谢谢。

好吧,我找到了解决方法。看起来不太理想,但确实有效

原代码

import java.sql.DriverManager
import groovy.sql.Sql

con = DriverManager.getConnection('jdbc:jtds:sqlserver://servername', 'user', 'password');
stmt = con.createStatement();

假设我们将 jar 保存在 /var/jenkins_home/test/jtds-1.3.1.jar 中,它可以更新为:

import java.sql.DriverManager
import groovy.sql.Sql

def classLoader = this.class.classLoader
while (classLoader.parent) {
    classLoader = classLoader.parent
    if(classLoader.getClass() == java.net.URLClassLoader)
    {
        // load our jar into the urlclassloader
        classLoader.addURL(new File("/var/jenkins_home/test/jtds-1.3.1.jar").toURI().toURL())
        break;
    }
}

// register the class
Class.forName("net.sourceforge.jtds.jdbc.Driver")

con = DriverManager.getConnection('jdbc:jtds:sqlserver://servername', 'user', 'password');
stmt = con.createStatement();

一旦此代码 运行 一次,jar 似乎就可以全局访问(即使在其他不加载 jar 的管道中)。

基于此,处理此问题的好方法似乎是在 Jenkins 初始化上,而不是在脚本中。我用这些内容创建了 /var/jenkins_home/init.groovy

def classLoader = this.class.classLoader
while (classLoader.parent) {
    classLoader = classLoader.parent
    if(classLoader.getClass() == java.net.URLClassLoader)
    {
        classLoader.addURL(new File("/var/jenkins_home/jars/jtds-1.3.1.jar").toURI().toURL())
        break;
    }
}

Class.forName("net.sourceforge.jtds.jdbc.Driver")

在那之后,脚本的行为似乎与我认为它应该如何与类路径中的 Jar 一起工作相似。