JenKins使用(一)

image-20240622013136692

Jenkins 是一个可扩展的持续集成引擎。

主要用于:

  • 持续、自动地构建/测试软件项目。
  • 监控一些定时执行的任务。

Jenkins拥有的特性包括:

  • 易于安装-只要把jenkins.war部署到servlet容器,不需要数据库支持。
  • 易于配置-所有配置都是通过其提供的web界面实现。
  • 集成RSS/E-mail通过RSS发布构建结果或当构建完成时通过e-mail通知。
  • 生成JUnit/TestNG测试报告。
  • 分布式构建支持Jenkins能够让多台计算机一起构建/测试。
  • 文件识别:Jenkins能够跟踪哪次构建生成哪些jar,哪次构建使用哪个版本的jar等。
  • 插件支持:支持扩展插件,你可以开发适合自己团队使用的工具。

初步下载JenKins

这里简单介绍在Linux服务器上使用Jenkins的过程。

首先利用Docker安装Jenkins

  1. docker search jenkins

    image-20240621215849968

  2. docker pull jenkins/jenkins:lts

    image-20240621215923365

  3. docker run -d -u root -p 8080:8080 -p 50000:50000 -v /var/jenkins_home:/var/jenkins_home -v /etc/localtime:/etc/localtime --name jenkins jenkins/jenkins:lts
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82

    ![image-20240621215950911](https://images-1318456035.cos.ap-shanghai.myqcloud.com/imgs/image-20240621215950911.png)

    ​ 我们可以看到,此时Jenkins已经在服务器进程中运行了(忽略一直在运行的MySql)

    接下来打开浏览器,输入服务器的 ip 地址,以及我们映射的端口号

    首先会弹出需要进入日志中查看首次登陆密码的界面

    ![image-20240621220217657](https://images-1318456035.cos.ap-shanghai.myqcloud.com/imgs/image-20240621220217657.png)

    输入该命令查看密码后,输入密码即可

    ![image-20240621220244056](https://images-1318456035.cos.ap-shanghai.myqcloud.com/imgs/image-20240621220244056.png)

    进入了JenKins界面



    ## 如何配置使JenKins打包后自动启动服务

    首先需要下载 Publish Over SSH 插件

    ![image-20240622165127155](https://images-1318456035.cos.ap-shanghai.myqcloud.com/imgs/image-20240622165127155.png)

    进入 系统管理-系统配置

    ![image-20240622165214621](https://images-1318456035.cos.ap-shanghai.myqcloud.com/imgs/image-20240622165214621.png)

    拖到最底部,去配置我们的ssh连接服务器的配置

    ![image-20240622165324650](https://images-1318456035.cos.ap-shanghai.myqcloud.com/imgs/image-20240622165324650.png)

    配置完成后点击保存

    接下来点击需要配置启动的服务

    ![image-20240622165510239](https://images-1318456035.cos.ap-shanghai.myqcloud.com/imgs/image-20240622165510239.png)

    新增一个通过SSH执行命令的配置步骤

    在Name中选择我们刚刚配置的服务器,exec command输入我们需要执行的脚本命令,这里给出我的示例

    ![image-20240622165522460](https://images-1318456035.cos.ap-shanghai.myqcloud.com/imgs/image-20240622165522460.png)

    ```shell
    cp /var/jenkins_home/workspace/maple-club-subject/maple-club-subject/maple-club-subject-starter/target/maple-club-subject-starter.jar /var/jenkins_home/jar/

    #!/bin/bash
    APP_NAME=maple-club-subject-starter.jar
    LOG_NAME=maple-club-subject-starter.log
    pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}'`

    function is_exist(){
    pid=`ps -ef|grep $APP_NAME|grep -v grep|awk '{print $2}'`
    if [ -z ${pid} ]; then
    String="notExist"
    else
    String="exist"
    fi
    echo $String
    }

    str=$(is_exist)
    if [ ${str} = "exist" ]; then
    echo "检测到已经启动的程序,pid : ${pid}"
    kill -9 $pid
    else
    echo "程序未启动"
    echo "${APP_NAME} is not running"
    fi

    str=$(is_exist)
    if [ ${str} = "exist" ]; then
    echo "${APP_NAME}已经启动, pid : ${pid}"
    else
    source /etc/profile
    BUILD_ID=dontKillMe
    nohup java -Xms300m -Xmx300m -jar /var/jenkins_home/jar/$APP_NAME >$LOG_NAME 2>&1 &
    echo "程序已经重新启动..."
    fi

之后点击保存,重新构建项目,会发现在构建完成之后,Jenkins会去连接服务器后,执行刚刚我们写入的shell脚本,现在就实现了部署后自动启动服务的操作

image-20240622165655421

遇到的一些问题

JenKins 在操作maven的时候,报错没有权限。

image-20240622012516354

直接开放mvn文件的所有权限

确保 /var/jenkins_home/apache-maven-3.9.1/bin/mvn 文件有执行权限。通过运行 chmod +x /var/jenkins_home/apache-maven-3.9.1/bin/mvn 命令来添加执行权限

在linux中运行jar包报错,logback与slf4j冲突

image-20240622011929762

​ 在spring-boot-starter-web 依赖下面忽略 spring自己的logging,由于项目使用的是slf4j,但是springBoot自带的是logback,会产生冲突。

Minio

1
docker run -p 9000:9000 -p 9090:9090 --name minio -d --restart=always -e "MINIO_ACCESS_KEY=minioadmin" -e "MINIO_SECRET_KEY=zsj20021012" -v /mydata/minio/data:/data minio/minio server /data --console-address ":9090" --address ":9000"

image-20240622170407145

Nacos

nacos自动关闭问题

在部署nacos的时候,一开始设置的命令是

1
docker run -d --name nacos --privileged --cgroupns host -e MODE=standalone -p 8848:8848/tcp -p 9848:9848/tcp --restart=always -w /home/nacos nacos/nacos-server

使其自动重启,发现他会无限的重启。开始排查原因。

先让他不自动重启,再次运行。发现他会在启动后自动关闭

怀疑是堆内存错误。

1
journalctl -k | grep -i -e memory -e oom

journalctl -k 是用来查看内核日志的命令。-k 或 –dmesg 参数表示只显示内核消息。

grep -i -e memory -e oom 是用来在这些日志中搜索特定的文本。-i 参数表示忽略大小写,-e 参数用来指定要搜索的文本,这里是 “memory” 和 “oom”。

所以,这个命令的作用是查看内核日志中所有与内存或者内存不足(OOM)有关的条目。

image-20240626021101149

发现果然是堆内存抛异常。

将堆内存分配小一点尝试。

1
docker run -d --name nacos --privileged --cgroupns host -e JVM_XMX=256m -e MODE=standalone -e JVM_XMS=256m -e JVM_XMN=128m -p 8848:8848/tcp -p 9848:9848/tcp --restart=always -w /home/nacos nacos/nacos-server

image-20240626021419937

启动成功且不会关闭

排查了很久。。。最后才发现真的是OOM。。。

还有一个问题,怀疑是nacos版本问题,导致docker容器运行的时候,cpu占用率直逼200%

docker stats

image-20240626194446758

重新拉取版本尝试

image-20240626194835632

发现还是不行。

现在发现,如果启动了Jenkins服务,Nacos则会占用过高,如果关闭了Jenkins服务,nacos可以正常使用。

不过还是要显示jvm的参数才可以正常使用

破案了,服务器内存太少了,原来是2g内存,升级到4g后,没有该问题。。。

nacos实现动态配置bean

首先需要注意spring-cloud-starter-alibaba-nacos-config版本与spring-boot的版本问题,spring-boot 2.4.2对应的为

1
2
3
4
5
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2021.1</version>
</dependency>

否则会存在依赖错误。

使用VPN的时候,无法访问服务器上的nacos。

image-20240627233248791

image-20240627233614646

想要让bootstrap.yml起作用,需要引入依赖

1
2
3
4
5
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
<version>3.0.4</version>
</dependency>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Configuration
@RefreshScope
public class StorageConfig {

@Value("${storage.service.type}")
private String storageType;

@Bean
@RefreshScope
public StorageAdapter storageAdapter() {
if("aliyun".equals(storageType)){
return new AliyunStorageAdapter();
}else if("minio".equals(storageType)){
return new MinioStorageAdapter();
}else{
throw new IllegalArgumentException("未找到对应的文件存储处理服务类型");
}
}
}

用以上注解,可以使得bean根据nacos上的配置动态加载